前言
最近翻看面试题目,无意中发现了这个题目。所以自己就写一个demo。感觉很有趣,特分享出来。
实现思路
我们分析一下,什么叫图片添加水印?常见的添加水印都是在图片上面添加一个图层(内容:防伪标识或者是公司的logo之类)。
我们去淘宝找人设计的话,一般都是给添加了水印的图片。只要不给你原型图,基本上无法去除水印。
写到这里我们基本上可以判断,所谓的水印技术,就是两张图片。一张是我们的原图,另一种就是水印图片,然后水印图片就是那种透明背景的图片,这样两张图片叠加,既可以看见原图的内容,还加了标识。
方向确定了。现在我们需要考虑的就是如何让两张图片上下覆盖(请不要想着css实现,因为我们最终是要以图片的形式展示)。因为最后是要形成一张照片,所以就需要两张照片融合。
联想现实,我们如何让两个物体融合,固体肯定是无法直接融合。那么我们就需要将两块固体分别融化,然后按照规则,合并到一起。接着变回固体。
思路清晰了。
首先我们就是将两张图片,原图以及logo图片分别,变成二进制流(base64)。然后以canvas为画板,就像刷油漆一样,先画一层原图的样式,然后再将我们的logo覆盖上去。
实现:将图片变成二进制流
这个地方实现思路比较简单,主要是借助HTML5 的FileReader读取文件的信息,并将其转为base64。
/**
* 将文件转换为base64
* 这个函数我在 大文件上传那篇文章里也用过,感兴趣的同学可以去看看
*/
function fileParse (file, type) {
const caseType = {
'base64': 'readAsDataURL',
'buffer': 'readAsArrayBuffer'
}
const fileRead = new FileReader()
return new Promise(resolve => {
fileRead[caseType[type]](file)
fileRead.onload = (res) => {
resolve(res.target.result)
}
})
}
实现:刷油漆式的在canvas上绘制两张图片
利用了canvas 的 drawImage方法。
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
参数 | 描述 |
---|---|
img | 规定要使用的图像、画布或视频。 |
sx | 可选。开始剪切的 x 坐标位置。 |
sy | 可选。开始剪切的 y 坐标位置。 |
swidth | 可选。被剪切图像的宽度。 |
sheight | 可选。被剪切图像的高度。 |
x | 在画布上放置图像的 x 坐标位置。 |
y | 在画布上放置图像的 y 坐标位置。 |
width | 可选。要使用的图像的宽度。(伸展或缩小图像) |
height | 可选。要使用的图像的高度。(伸展或缩小图像) |
水印图片的形成,就是利用drawImage 方法在canvas上绘制就可以了。
总结
整体来讲思路比较简单,具体实现还是有些小细节。具体代码可以关注我的公众号聪明可爱小轩轩回复 mergeImg 领取。需要注意的一点上,代码需要运行的服务下,建议使用http-serve。
同时,我的例子还有很多扩展的地方,比如我们可以移动我们的的水印的位置,这个在drawImage 中就可以配置。
当然这个例子有个鸡肋的地方,就是需要有一个水印图片。其实利用我们的所学知识就可以实现。我们正常中,可以将html生成图片下载,给用户一个输入框,输入水印文字,然后生成图片,再走上面的流程。文字大小,字体颜色,字体位置均可以。
这是我的一个实现思想,不一定对,但是确实可以尝试,明天争取实现这个功能,并分享出来。
如果感觉我的文章对你有帮助,请点赞,关注。您的点赞,关注就是我持续创作的动力。感谢!!!