问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

使用svg创建动态水印内容

发布网友 发布时间:2024-09-30 17:21

我来回答

1个回答

热心网友 时间:2天前

使用svg创建动态水印内容

查看css+svg效果演示

相关很牛逼的库推荐:watermark-dom-基于DOM对象实现的BS系统的水印

简单的实现原理

传统的动态水印都是先用canvas渲染上对应的文案,生成透明png。然后使用::after或者背景图的方式,覆盖在需要被加水印的节点上,以此来实现加水印的效果

传统的方式存在一下几个问题:

每次都要用canvas(相对来说耗费的资源较多)

2022年了,很容易被人打开F12,然后删除对应的节点/对应的背景图样式(不太安全)

针对上面2个问题,还是有办法解决的

使用svg代替canvas

使用svg的思路很简单,就是利用background-image:url('svgpath.svg')也能正常显示的特性(毕竟svg其实就是特殊一点的图片)。

准备一个svg,svg复杂的原理就不去深究了,说一下这次需要用得上的最基础的svg需要具备什么样的内容:

<svgxmlns="http://www.w3.org/2000/svg"width="144px"height="144px"><textx="18"y="0"fill-opacity="0.1"fill="#000"transform="translate(0,144)rotate(-45)"font-size="18">Jioho的博客</text></svg>

宽高就限制这个水印的大小。我根据文本的长度给了144px

要想显示文本,就用到了<text>标签

x="18"这个的作用是基线的偏移,因为字体大小是18px,可以粗糙的理解为单个字符就是18*18px的。如果x轴不往下偏移18px,那么字体会飘到上面去

fill-opacity="0.1"毕竟是水印,需要给点透明度

fill="#000"文本填充的颜色,纯黑+上面的0.1透明度

transform就和css的transform是一样的,控制x,y轴的偏移和旋转角度。我的水印想做45°的

基础的介绍就是这样了。

看到demo-1就会发现静态水印就是这么简单就实现了。

动态控制svg的内容

这一趴需要一些前置知识,比如css变量、以及文字转SVG图像在线转换工具。

实现的整体思路也可以参考张鑫旭-如何让文字作为CSS背景图片显示?

总的来说就是:

/*背景图支持直接写入svg内容*/background-image:url('<svgxmlns="http://www.w3.org/2000/svg"width="144px"height="144px"><textx="18"y="0"fill-opacity="0.1"fill="#000"transform="translate(0,144)rotate(-45"font-size="18">Jioho的博客</text></svg>');/*出于安全限制,需要对字符进行转义*/background-image:url("data:image/svg+xml,%3Csvgxmlns='http://www.w3.org/2000/svg'width='144px'height='144px'%3E%3Ctextx='18'y='0'fill-opacity='0.1'fill='%23000'transform='translate(0,144)rotate(-45)'font-size='18'%3EJioho的博客%3C/text%3E%3C/svg%3E");

data:image/svg+xml就是用文字转SVG图像在线转换工具转换出来的

到这里,我们已经把文件类型的svg转换到页面上的svg,接下来只需要把水印的关键字Jioho的博客替换掉,动态水印就成功一半了

先说css变量,写法如下,不理解的请反复观看css变量并背诵全文:

.watermark{--watermark:url("data:image/svg+xml,%3Csvgxmlns='http://www.w3.org/2000/svg'width='144px'height='144px'%3E%3Ctextx='18'y='0'fill-opacity='0.1'fill='%23000'transform='translate(0,144)rotate(-45)'font-size='18'%3EJioho的博客%3C/text%3E%3C/svg%3E");background-image:var(--watermark);/*其余样式省略...*/}

css变量定义成功后,那么用js控制css变量也是轻而易举了

在加上一些简单的控制,比如:

svg的宽度就约等于文字的长度*字体大小

整个水印做下来是一个正方形,所以高度=宽度

用到.setProperty('--watermarksvg',watermarksvg)为css变量赋值

letsvgText='Jioho的博客'letfontSize=18letsvgWidth=fontSize*svgText.lengthletsvgHeight=svgWidthletrotate=-45watermarksvg=`url("data:image/svg+xml,%3Csvgxmlns='http://www.w3.org/2000/svg'width='${svgWidth}px'height='${svgHeight}px'%3E%3Ctextx='${fontSize}'y='0'fill-opacity='0.1'fill='%23000'transform='translate(0,${svgHeight})rotate(${rotate})'font-size='${fontSize}'%3E${svgText}%3C/text%3E%3C/svg%3E")`document.querySelector('.watermark').style.setProperty('--watermarksvg',watermarksvg)

至此,动态的svg就实现了,svg动态后,那作为背景的svg水印也就动态变化了(具体效果可以看demo-2)

水印事件穿透的问题

做完上面的步骤总体来看是没啥问题的,可是毕竟蒙了一层水印,一些点击事件/拖动事件穿透不下去,所以用到一个简单的属性,让水印的这一层不要拦截任何事件,全部穿透给下一层

.watermark{/*省略其余代码...*/pointer-events:none;}水印最重要的一趴,安全性

众所周知前端是没有秘密的。以上说的内容包括demo-1至demo-4,打开控制台很容易就可以把水印的那一层after删除/把css就删了,所以这种水印防君子不防**

介绍另外一个很重要的APIMutationObserver

简单来说就是,监听到水印层被删除的时候,就立刻重新补上一个水印层(因为要监听dom的变化,所以这时候的水印就不能用after了,就必须来上一个div层做水印)

可是如果我们直接监听.monitoring。如果这一层被直接删除他是并不会触发监听事件的,所以我们还得连带着水印+内容的父级去监听,把监听的配置childList打开,监听这个div下子节点的变化

当监听的对象mutationsList出现div被删除了mutationsList[0].removedNodes。并且删的就是水印层的话,直接往父级重新添加一个水印层即可

style样式同理,不过我们要把style全部都写成行内样式,而且尽可能不保留css文件控制样式,这样就算想加样式也得修改dom节点上的style标签,这样就能触发我们的监听,从而把style样式重新改回去达到防篡改的目的(具体实现可以看demo-5)

<divclass="warkmask-conotainer"><!--水印层--><divclass="warkmask-deletemonitoring"style="background-image:var(--watermarksvg);"></div><!--水印层-end--><!--要被打码的内容--><divclass="content-box"></div></div>varobserver=newMutationObserver(function(mutationsList,observer){mutationsList.forEach(item=>{if(item.removedNodes.length>0){item.removedNodes.forEach(removeNode=>{if(isMonitoring(removeNode)){item.target.appendChild(removeNode)}})}})})document.querySelectorAll('.monitoring').forEach(item=>{observer.observe(item.parentNode,{attributes:true,childList:true,subtree:true})})追求更严谨水印安全性

如果上面的svg动态方案还是觉得不妥,建议就直接使用watermark-dom-基于DOM对象实现的BS系统的水印

这个库实现的思路其实和上文描述的差不多,唯一的区别就是为了防篡改,他们就连水印的内容也都是用div渲染的。这样就能很好的触发监听,防止篡改和删除了

并且用了影子节点(shadow-root)这种节点必须通过js创建,然后内部的样式不受外部的控制和影响

一些比较重要的样式,都用了style="pointer-events:none!important;display:block!important"的形式(行内样式+import,神仙来了都覆盖不了你的样式,加上dom节点的监听,根本删不掉这段样式,就能保证一直存在了)。不过千算万算少算了一步就是透明度和样式的问题(待会就去提个issues)

这也侧面说明(前端没有绝对的安全),不过这个库已经把非常多的情况考虑进去了(主要是有现成的轮子)

最后

使用svg代替canvas做水印其实也是为了方便快捷,减少了canvas的渲染导出图片的操作,很好的利用了svg可以作为背景图的特性

加上svg转换工具,配合css变量已经可以实现很丰富的动态水印效果了。如果在加上MutationObserver的加持,安全性可以更进一步

以上都是简单的理论知识和简单的demo,使用的话还是推荐watermark-dom-基于DOM对象实现的BS系统的水印

原文:https://juejin.cn/post/7103736071933919262
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
Linux系统安装FTP服务器 Linux系统的网络文件共享 建筑的七盏明灯的内容简介 面向对象设计七大原则 简单说 交互设计七大定律 交互设计的“根”——七大定律 交互设计原则和理论2——七大定律 七大设计原则 附近的加油站有哪些 附近的加油站有哪些地方 css下载安装? css样式写出三角形,宽高自适应的正方形,扇形! 抖音视频什么时候发最热门? 抖音什么时候发作品流量大? ...和学位证毕业证行吗?还是必须要中文原件的翻译件? “抉目观亡国”的出处是哪里 ...申请美国 本科学校开的成绩单 毕业证 学位证 都要自己翻译么 用拿到... 过年去哪里旅游比较好国内 【421】成语故事:抉目东门 帮我解解梦吧 我做梦梦到蜈蚣了 春节旅游排名前十的城市_江西过年旅游必去十大景点 读书郎学习机是平板的好还是翻盖的好 读书郎c15有哪些缺点和优点 内地有多少家比较好的经纪公司啊? 昨晚我梦见一对儿山鸡在低空飞,姐姐跑过去伸手抓住了一个,另一只跑了... ...男生就来找她看她了,男生什么意思?他们两个以前是同学 电脑开机可以进入,就是显示器接收不到信号?请问怎么回事。电脑拿鼠标乱... 电脑连显示器无信号是什么原因? 我的新浪微博用户名可以登录上去,用户名和密码也都记得... 婚礼预算包含的费用项目有哪些一些额外支出也不可忘 oppo手机里相册里自带云相册,手机丢了如何找回照片 apple watch series4电池如何更换 水养富贵竹施什么肥料 poi设置行高_poi设置行高列宽 用poi包的hssf,怎样让excel中的单元格cell里面的文字"自动换行 POI导出excel时要怎么样才能够直接插进那个单元格中而不是整行添加... 暴风影音怎么下载电视剧,为什么每次下载都没反应?还是只能边播边下... 手机上的暴风影音怎么下载电视剧 Beoplay e8无法连接配对怎么办? 为什么我家网络无法上网了呢? ...怎么样才能玩的了C9(第九大陆) 电脑型号 联想 ThinkPad R61/... 跑跑卡丁车手游博特怎么样 博特技能属性介绍 适当升级R61 大家觉得小米mix2换三星S8怎么样 ThinkPad R61的机子开机后硬盘灯(一个圆柱两小箭头那个)一直闪到关机... 小米mlx2好还是s8好 小米mix2和三星s8谁的 法语翻译 陈先生早上好 新股发行的面值都是1元,为什么新股发行价都不同?这个价格是怎么定出来的... 梦到一个认识的人上吊自杀