原创 zcc
date 2020-03-05
前些天突然发现内网上的好多页面都添加了水印,如下图所示,每个人的名字作为背景图整齐排列,这是怎么实现的呢?
首先想到的是给页面加背景图,但是背景图的内容要动态绘制,怎么办呢?先思考再往下看:
鉴于现代浏览器的日益更新和IE旧家族的逐渐没落,很容易想到使用canvas实现。
由于我的需求是使用用户名或者其它指定文字,这里重点介绍一下fillText。
先来简单了解一下fillText的语法吧:
fillText(text,x,y,maxWidth)
text:规定在画布上输出的文本。
x:开始绘制文本的 x 坐标位置(相对于画布)。
y:开始绘制文本的 y 坐标位置(相对于画布)。
maxWidth:可选,允许的最大文本宽度,以像素计。
下面再来想想实现一个灵活可定制的文字图片,除了文字内容,还需要传些什么参数呢?
比如图片大小,文字颜色,文字的旋转角度,字体,显示图片的容器等等;
参数是供用户自己根据实际情况调整的,假如用户不希望一个个填写这些差不多的内容怎么办呢?
对了,使用默认值;
综上考虑,代码大致如下:
function waterMark({
width=300, //画布宽度
height=200, //画布高度
rotate = 30, //旋转角度
color = "#ccc", //字体颜色
textAlign = 'center', //文字对齐方式
textBaseline = 'middle',
font = "20px microsoft yahei",
content = "zcc", //最重要的,水印的内容
opacity = '0.6',
zIndex = 999,
container = document.body, //水印显示在哪里
} = {}){
let cvs =document.createElement('canvas');
let ctx = cvs.getContext('2d');
cvs.width = width;
cvs.height = height;
ctx.rotate(Math.PI / 180 * rotate);
ctx.fillStyle = color
ctx.font = font
ctx.textAlign = textAlign
ctx.textBaseline = textBaseline
ctx.fillText(content, parseFloat(width/2),parseFloat(height/2))
let url = cvs.toDataURL()
let div = document.createElement('div')
div.style = `
position:absolute;
width:100%;
height:${container.scrollHeight}px;
pointer-events:none;
top:0;
bottom:0;
opacity: ${opacity};
z-index: ${zIndex};
background-repeat:repeat;
background-image:url(${url});
`
container.appendChild(div)
}
实现很简单是不是?使用就更简单了,由于我们的代码很贴心的给了很多默认参数,最简单的使用方式是直接调用waterMark();
不过这时候显示的内容可是作者我的名字哦,所以如果自己使用,最起码这样使用waterMark({content:'your name'});
下面我们再稍微扩展一下,假如用户并不想要你给他自动加背景图,就是想要一个图片,自己来决定图片的使用,又该怎么办呢?
答案也很简单, 在函数里加个参数, onlyURL=false,默认false,如果为true,直接返回url,否则才去创建背景元素:
// 绘制图片部分参考上文
let url = cvs.toDataURL()
if(onlyURL){
return url;
}
let div = document.createElement('div')
div.style = `
position:absolute;
width:100%;
height:${container.scrollHeight}px;
pointer-events:none;
top:0;
bottom:0;
opacity: ${opacity};
z-index: ${zIndex};
background-repeat:repeat;
background-image:url(${url});
`
container.appendChild(div)
简单的加水印功能已经完成了,是不是到这就结束了呢?
其实如果再扩展一下,还有很多可以实现的功能点,比如:
上述实现文字都是单行的,如果想要多行显示要怎么做呢?
上述实现是作为一张背景图添加到页面,稍微懂点前端的人是知道怎么去掉水印的,水印的防护功能就没用了,此时又该怎么处理呢?
上述实现只是单纯的显示文字,如果用户提供一张图片又该怎么做呢?
作为具有分享精神的互联网人,我们怎样提供给别人使用呢?
上面这些问题就留给感兴趣的小伙伴去思考、实践了。
前端的探索是无止境的,小伙伴们是不是跃跃欲试了,赶紧行动起来吧!