文字水印是一种强提示,一般会用在前端展示敏感、权利声明等场景下。我们简单介绍几种方法。一般的从实现上来说,大概有三种方式来实现:后端生成、svg、canvas。下面具体来说:
后端生成
顾名思义,肯定是后端通过一些方法将水印生成。前端直接给需要的 dom 元素加上背景。这样做有很多优点。
比如足够灵活,可以将一些“别的”信息注入到图片里面。比如完全可以把JS,CSS任意文本文件加密成一张图片。
比如足够统一。一个图片地址,在配置好了 CORS 的情况下可以随意使用。如果水印的内容与登录态有关,则可以在配置了单点登录 SSO 的多个系统中共同使用。如果水印升级了也能 0 配置的在各个系统里应用起来。
比如足够兼容。上到远古时代的 IE4,到现在的更坑爹的 IE9、10、 Edge。通通支持。
但是缺点也很明显。就是多一次 http 请求。个性化和定制化程度有限。
具体怎么生成,这里不展开了。
SVG
代码比较简单,直接贴出来
function getSVGTextBase64(text, svgStyle) {
var svgNS = 'http://www.w3.org/2000/svg';
function createTag(tag, objAttr) {
var oTag = document.createElementNS(svgNS, tag);
for (var attr in objAttr) {
oTag.setAttribute(attr, objAttr[attr]);
}
return oTag;
}
svgStyle = Object.assign({
'width': '50px',
'height': '50px',
'text-anchor': 'left',
'font-size': '12px',
'transform': 'translate(0 50) rotate(-15)',
'x': '0',
'y': '1em',
}, svgStyle);
var oSvg = createTag('svg', { 'xmlns': svgNS, 'width': svgStyle.width, 'height': svgStyle.height, });
var oText = createTag('text', svgStyle);
oText.innerHTML = text;
oSvg.appendChild(oText);
return oSvg;
}
Canvas
Canvas 生成水印简直就是小儿科了。我们动手搞一下。
- 首先,拿到你的文字和文字在 dom 中展示的宽度和高度。
const text = '版权所有 违者必究';
const div = document.createElement('div');
div.style.color = 'rgba(31, 56, 88, .04)';
div.style.font = '14px 黑体';
div.innerHTML = `<span>${text}</span>`;
document.body.appendChild(div);
// 拿到宽度
let width = div.getElementsByTagName('span')[0].offsetWidth;
// 高度最小应该是文字的高度。不然显示不全。
let height = 14。
// 别忘了移除这个多余的 div
div.parentNode.removeChild(div);
这个时候是不是完了呢?如果你水印中的文字跟前面示例图中的文字一样,有一个倾斜度的话,那还没有结束。为什么呢?因为如果文字有倾斜度的话,最小高度肯定就不能是文字的高度了。
这就用到了我们初中学到的三角函数了。假定文字的倾斜度数是 30 度。那么高度应该是多少呢?
const alpha = 30 * Math.PI / 180;
height = width * Math.sin(alpha);
到这儿还没完。这里有个坑,JavaScript 计算浮点数的尿性大家都知道吧?
所以我们还要再做一下处理:
height = Math.ceil(height);
- 接着,开始画 Canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
// 坐标轴先旋转 alpha 度,这样可以得到一个
ctx.rotate(alpha)
// 上面的文字字体、颜色等样式
ctx.font = '14px 黑体';
ctx.fillStyle = "rgba(31, 56, 88, .04)";
// 填充文字
ctx.fillText(text, 0, 0);
// 再转回来
ctx.rotate(-alpha)
- 最后,轻轻松松拿到水印 url
直接一句
canvas.toDataURL('image/png')
整个世界都安静了,热泪盈眶啊。。。如果说有缺点的话,就是 base64 太长了。虽然我很想长,但这时候不想。怎么办?好办, 用 createObjectURL
处理一下。
canvas.toBlob(function (blob) {
// 用的时候 create 一下
var url = URL.createObjectURL(blob)
// ...
});
当然这些你不太用你自己亲手写啦,有一些第三方库可以直接用。比如 hustcc 提供的 alimask 可以在 node 或者 浏览器环境中直接使用。