实现原理

通过在 canvas 上绘制出字体,设置好样式,然后以图片的样式导出,最后用图片作为水印层的背景图。

实现效果

全屏实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IUMpCYhj-1663052343162)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bbccf283a0b44d27bb31d93cd4a16e42~tplv-k3u1fbpfcp-watermark.image?)]

实现方法

(1)在src下创建一个util文件夹,创建一个watermark.ts文件

export const getmark = () => {const setWatermark = (str: any) => {const id = "1.23452384164.123412416";\if (document.getElementById(id) !== null) {document.body.removeChild(document.getElementById(id)!);}\//创建一个画布const can = document.createElement("canvas");//设置画布的长宽can.width = 150;can.height = 120;\const cans = can.getContext("2d")!;//旋转角度cans.rotate((-15 * Math.PI) / 180);cans.font = "18px Vedana";//设置填充绘画的颜色、渐变或者模式cans.fillStyle = "rgba(200, 200, 200, 0.40)";//设置文本内容的当前对齐方式cans.textAlign = "left";//设置在绘制文本时使用的当前文本基线// cans.textBaseline = "Middle";//在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)cans.fillText(str, can.width / 8, can.height / 2);\const div = document.createElement("div");div.id = id;div.style.pointerEvents = "none";div.style.top = "30px";div.style.left = "0px";div.style.position = "fixed";div.style.zIndex = "100000";div.style.width = document.documentElement.clientWidth + "px";div.style.height = document.documentElement.clientHeight + "px";div.style.background ="url(" + can.toDataURL("image/png") + ") left top repeat";document.body.appendChild(div);return id;};\// 该方法只允许调用一次const watermark = (str: string) => {let id = setWatermark(str);setInterval(() => {if (document.getElementById(id) === null) {id = setWatermark(str);}}, 500);window.onresize = () => {setWatermark(str);};};return { watermark };};

(2)设置水印:在需要水印的页面添加如下代码

<script setup lang="ts">
import {onMounted, onUnmounted, ref} from 'vue';
import { getmark } from "./util/watermark";const { watermark } = getmark();onMounted(() => {watermark("你的名字");//水印名});onUnmounted(() => {watermark("");});
</script>

vue2 的使用方法基本相同,只需换为对应的生命周期即可。下面把相应代码也贴出来,供大家参考。

(1)项目中新建一个 watermark.js 文件

let watermark = {};let setWatermark = (text, sourceBody) => {let id =Math.random() * 10000 +"-" +Math.random() * 10000 +"/" +Math.random() * 10000;if (document.getElementById(id) !== null) {document.body.removeChild(document.getElementById(id));}let can = document.createElement("canvas");can.width = 120; //设置水印之间的左右间距can.height = 80; //设置水印之间的上下间距let cans = can.getContext("2d");cans.rotate((-20 * Math.PI) / 180);cans.font = "15px Vedana";cans.fillStyle = "rgba(0, 0, 0, .5)";cans.textAlign = "left";cans.textBaseline = "Middle";cans.fillText(text, can.width / 20, can.height);let water_div = document.createElement("div");water_div.id = id;water_div.className = "watermarkClass";water_div.style.pointerEvents = "none";water_div.style.background ="url(" + can.toDataURL("image/png") + ") left top repeat";if (sourceBody) {water_div.style.width = "100%";water_div.style.height = "100%";sourceBody.appendChild(water_div);} else {water_div.style.top = "3px";water_div.style.left = "0px";water_div.style.position = "fixed";water_div.style.zIndex = "100000";water_div.style.width = document.documentElement.clientWidth + "px";water_div.style.height = document.documentElement.clientHeight + "px";document.body.appendChild(water_div);}return id;
};/***  该方法只允许调用一次*  @param:*  @text == 水印内容*  @sourceBody == 水印添加的位置,不传就是body* */
watermark.set = (text, sourceBody) => {const domArr = Array.from(document.getElementsByClassName("watermarkClass"));for (let i = 0; i < domArr.length; i++) {const element = domArr[i];// element.parentNode.removeChild(element);element.remove();}if (text == "") {return;}setWatermark(text, sourceBody);// let id = setWatermark(text, sourceBody);// setInterval(() => {//   if (document.getElementById(id) === null) {//     id = setWatermark(text, sourceBody);//   }// }, 2000);// window.onresize = () => {//   setWatermark(text, sourceBody);// };
};export default watermark;

(2)main.js 中引入 watermark.js

// 引入水印文件地址
import watermark from './util/watermark.js'
Vue.prototype.$watermark = watermark

(3)全屏水印

<template><div class="page"></div>
</template><script>
export default {data() {return {};},mounted(){this.$watermark.set("水印")},beforeDestroy() {this.$watermark.set("");}
};
</script><style scoped>
.page{width: 100%;height: 100%;background-color: skyblue;
}
</style>

局部水印:

<template><div class="page"><div ref="content" style="width: 500px;height: 500px;border: 2px solid red;"></div></div>
</template><script>
export default {data() {return {};},mounted(){this.$watermark.set("水印",this.$refs.content)},beforeDestroy() {this.$watermark.set("",this.$refs.content);}
};
</script><style scoped>
.page{width: 100%;height: 100%;background-color: skyblue;
}
</style>

vue3 项目添加水印的实现方法相关推荐

  1. vue3项目实战中的接口调用方法(二)fetch用法 (前后端交互) get请求/post请求/put请求/delete请求

    vue3项目实战 fetch调用接口

  2. 使用vite安装vue3项目,vue3安装router和vuex

    目录 安装vite/创建vue3项目 安装router 安装vuex vite+vue3的axios配置及跨域 安装vite/创建vue3项目 推荐vite+vue3+elementplus教程,看这 ...

  3. 给 vite 创建的 Vue3 项目配置 ESLint

    目录 前言 一.下载安装相关的依赖包 二.配置 .eslintrc.js 1.重点成员解析 (1).parserOptions 2..eslintrc.js 配置案例 三.配置 .eslintigno ...

  4. vue3项目返回第三方页面onBeforeUnmount和onBeforeRouteLeave失效问题

    vue3项目埋点需求,需记录页面浏览时长,入口在第三方页面,从vue3页面返回到第三方页面时,onBeforeUnmount.onBeforeRouteLeave全部失效不执行,在vue3项目里组件之 ...

  5. [项目实战] 使用Idea构建单页面Vue3项目(不使用node、npm)

    前言 某天张三对小花说,我需要在一台新电脑上实现一个前端的漂亮页面:比如京东手机首页(m.jd.com). 小花这时吭哧吭哧的去新电脑上安装nodejs.npm,然后在本地使用npm构建vue3项目, ...

  6. vue3项目使用了element-plus中的el-table表格组件,缩放浏览器网页时,报错如下: ResizeObserver loop limit exceeded at eval (w

    错误描述: vue3项目使用了element-plus中的el-table表格组件,缩放浏览器网页时,报错如下: ResizeObserver loop limit exceeded at eval ...

  7. 【Vue】新建一个Vue3项目

    目录 1.新建vue项目 2.路径更改至新建的vue项目处 3.安装cnpm 4.cnpm安装vant3 5.安装babel-plugin 6.安装vue路由 7.安装axios 其他注意事项 仅用于 ...

  8. java项目怎样强制删除手机缓存_Myeclipse清理项目缓存的几大方法

    今天小编就为大家分享一篇关于Myeclipse清理项目缓存的几大方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧 相信大家被项目缓存折腾过吧,这里罗列几条 ...

  9. Android Studio导入Eclipse项目的两种方法

    Android Studio导入Eclipse项目有两种方法,一种是直接把Eclipse项目导入Android Studio,另一种是在Eclipse项目里面进行转换,然后再导入Android Stu ...

最新文章

  1. cocos2dx 优化略记
  2. Batch Size对神经网络训练的影响
  3. Windows下在Django中创建项目时ImportError: No module named django.core解决方法
  4. Android 计步功能-简单实现
  5. 【Android Studio安装部署系列】十八、Android studio更换APP应用图标
  6. 活动回顾 | 8月7日Apache Flink Meetup
  7. LDAP 中 CN, OU, DC 的含义
  8. matlab生成均匀部分散点图,应用halton序列生成均匀散点图
  9. android edittext获取 time值,在Android EditText中实现日期时间选择器(DatePicker和TimePicker)...
  10. groovy+mysql数据库_groovy - groovy连接数据库
  11. TIA博途_如何更新程序中的指令版本和CPU固件版本?
  12. MySQL批量插入(使用mybatis实现mysql数据库的批量插入操作)
  13. 具有相关关系的数据处理:线性混合模型与广义线性混合模型
  14. Windows 7下可以使用的虚拟光驱软件
  15. LeapFTP3.1注册码
  16. FOI2022 夏令营基础班 day1题解
  17. 好看的html页脚,Photoshop教程:设计非常漂亮的网页页脚
  18. 沉痛悼念张孝祥老师逝世
  19. 靓号,java正则表达式的实现
  20. 基于SPI协议的Flash驱动控制-扇区擦除

热门文章

  1. 如何通过编程方式获取alexa排名的数据
  2. 一文说清丨科学认识幽门螺旋杆菌
  3. 计算机二级ms office英语翻译,2015年计算机二级MS Office习题及答案解析(3)
  4. 出现“Windows资源管理器已停止工作”错误
  5. 用PhotoShop如何替换图片中的文字
  6. R语言计算回归模型残差平方和(Residual Sum of Squares)实战,并基于残差平方和比较模型优劣
  7. TouchSlide滚动插件BUG
  8. CVPR2018资源汇总-
  9. 程序员面试,面试官不看技术,只看员工有没有穿短裤,眼光独特
  10. 旷世轻量化网络ShuffulNetV2学习笔记