如何在博客园里给图片加水印(canvas+drag)?
如何在博客园里给图片加水印(canvas+drag)?
一、总结
一句话总结:
1、如何从根本上美化上传控件框(替代思想)?
解答:隐藏上传控件,并加了一个新的按钮在它前面用选择器来触发这个上传控件。
2、通过隐藏上传控件,并加了一个新的按钮在它前面用选择器来触发这个上传控件的方法,怎么拿到上传的文件?
解答:通过event对象,var imgFile = event.target.files[0]; dom中有event,jquery中也有
选择文件后,文件上传控件会触发change事件,此时可以拿到文件。
$('#target_file').change(function (event) {
var imgFile = event.target.files[0];
......
});
3、文件转化为图片的方法?
解答:文件转换为图片实际上首先需要读取文件,这里需要用到FileReader。通过FileReader的readAsDataURL函数读取文件可以获得Base64格式的图片数据,将图片数据赋值给一个Image对象。
4、怎么在图片上加水印?
解答:用canvas来给图片加水印。先将图片用drawImage渲染进canvas,再在指定的位置用fillText渲染文字即可,并将最后的canvas用toDataURL转化为图片数据即可。
5、拖动文字加水印的方法?
解答:在span元素上加drag事件。
当我们设置水印时,直接将文字渲染到canvas上,然后在文字上方安放一个颜色透明的内容为水印文字的span元素。
然后我们在这个span元素上加drag事件。
HTML5拖动功能网上一大堆,这里就不讲了。
6、拖动文字或者图片或者文件用的什么事件?
解答:用的drag事件。
7、因为博客园自动屏蔽了canvas标签和download属性,所以怎么实现在博客里面插入canvas标签和download属性?
解答:可以动态通过js插入。download属性:可以把download属性对应的标签一起插入进去。
// 此处通过这种方式将html插入,是因为博客园自动屏蔽了canvas标签和download属性
var initHtmlConstruct = function () {
$('#canvas-container').text('').append('<canvas id="target_canvas" width="100" height="100">浏览器不支持此功能,请升级</canvas><span draggable="true" id="watermark"></span>')
$('#toolbar').append('<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>');
}
8、jquery中动态插入一个元素用的方法是什么?
解答:$().append()。 $('#toolbar').append('<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>');
二、前言
var watermarkInfo = { fontSize: 18, // 像素值 fontFamily: 'cursive', content: '', color: '#fffbf0' };
三、实现过程中的问题与解决方案
代码什么的就不全部贴上来了,只是讲一下其中遇到的一些问题与实现思路。
这些问题您可能已经大多了解了,不过为了兼顾所有人,所以还是会将一些比较简单的技术点也讲一下。
整个实现过程中遇到的问题如下
- 获取图片
- 将上传文件转换为图片
- 在图片上加水印
- 拖动文字加水印
- 将最后修改的图片下载下来
四、获取图片
获取图片实际上就是用到文件上传控件,也就是
<input id="target_file" type="file"/>
然而原始的文件上传控件比较丑,所以隐藏此控件,并加了一个新的按钮在它前面
<a class="btn" id="btn_select_file" href="jacascript:void(0)">选择背景图</a> <input id="target_file" type="file" style="display:none" />
而想实现点击选择背景图按钮去选择文件,用以下代码即可
// 按下选择的背景图 $('#btn_select_file').click(function () { $('#target_file').click(); });
选择文件后,文件上传控件会触发change事件,此时可以拿到文件。
$('#target_file').change(function (event) { var imgFile = event.target.files[0]; ...... });
五、将文件转换为图片
文件转换为图片实际上首先需要读取文件,这里需要用到FileReader。
function setImgIntoCanvas(imgFile) { var reader = new FileReader(); reader.onloadend = function (e) { var dataURL = e.target.result; img.onload = function (event) { var ctx = document.getElementById('target_canvas').getContext('2d'); //将canvas大小设置为和图片一样大 setCanvasSize(event.target.naturalWidth, event.target.naturalHeight); ctx.drawImage(img, 0, 0); setCanvasImgToDownloadLink(); }; img.src = dataURL; }; reader.readAsDataURL(imgFile); resetWatermark(); };
以上为核心代码,通过FileReader的readAsDataURL函数读取文件可以获得Base64格式的图片数据,将图片数据赋值给一个Image对象。
六、在图片上加水印
七、拖动文字加水印
canvas虽然也能捕获事件,获取鼠标位置,并实现拖动文字效果,但是实现起来太麻烦。
所以这里采用更简单的方案。
当我们设置水印时,直接将文字渲染到canvas上,然后在文字上方安放一个颜色透明的内容为水印文字的span元素。
然后我们在这个span元素上加drag事件。
HTML5拖动功能网上一大堆,这里就不讲了。
主要讲一下实现思路:
在开始拖动时,重新用图片渲染canvas,使得之前渲染的文字消失。
在结束拖动时,获取到具体的位置,再重新将文字渲染进canvas。
这里说起来简单,其实还是有一些细节,包括css和js的配合,比如文字拖动到边界时的处理方式,又比如文字拖动到边界出现换行的情况。
还有一些其他的小坑点,需要你自己看代码去体会了。
这里贴出部分代码:
// 绑定移动水印相关事件 var bindEvent4DragWatermark = function () { $('#watermark').on('dragstart', function (e) { var ctx = document.getElementById('target_canvas').getContext('2d'); ctx.clearRect(0, 0, $('#target_canvas').width(), $('#target_canvas').height()); ctx.drawImage(img, 0, 0); // 显示可拖拽水印 $(this).addClass('selected'); watermarkInfo.offsetX = e.originalEvent.offsetX + canvasInfo.left; watermarkInfo.offsetY = e.originalEvent.offsetY + canvasInfo.top; }); // 让水印跟着鼠标移动 $('#watermark').on('drag', function (e) { var x = e.originalEvent.pageX; var y = e.originalEvent.pageY; if (x === 0 && y === 0) { return; } x -= watermarkInfo.offsetX; y -= watermarkInfo.offsetY; $('#watermark').css('left', x).css('top', y); }); $('#watermark').on('dragend', function (e) { // 调整位置,使水印无法超出canvas边界 var x = e.originalEvent.pageX - watermarkInfo.offsetX; var y = e.originalEvent.pageY - watermarkInfo.offsetY; if (x < 0) { x = 0; } if (y < 0) { y = 0; } var maxX = canvasInfo.width - watermarkInfo.width; var maxY = canvasInfo.height - watermarkInfo.height; if (x > maxX) { x = maxX; } if (y > maxY) { y = maxY; } $('#watermark').css('left', x).css('top', y); // 拖拽完水印,文本隐藏 $('#watermark').removeClass('selected'); setTextIntoCanvas(); }); // 让鼠标不显示禁用样式 $('#canvas-container').on('dragover', function (e) { e.preventDefault(); }); }
八、将最后修改的图片下载下来
之前我们已经讲到了用canvas的toDataURL函数获取最后的图片数据,然后关于下载就需要用到一个HTML5的download属性。
<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>
接下来是设置图片数据的代码
/** * 设置canvas图像到下载链接上 */ function setCanvasImgToDownloadLink() { var imgData = document.getElementById('target_canvas').toDataURL(); $('#download_file').attr('href', imgData); };
九、将功能写进博客里
至于这部分首先要申请JS权限。
其次如果观察仔细,还可以在我的代码中看到下列代码
// 此处通过这种方式将html插入,是因为博客园自动屏蔽了canvas标签和download属性 var initHtmlConstruct = function () { $('#canvas-container').text('').append('<canvas id="target_canvas" width="100" height="100">浏览器不支持此功能,请升级</canvas><span draggable="true" id="watermark"></span>') $('#toolbar').append('<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>'); }
至于原因注释里也写了,是因为博客园的编辑器屏蔽了canvas标签和download属性。
十、总结
总的来说,这其实是一个很小的功能,但是要把它做得好用一点,涉及到的知识点并不少,也不并不仅仅我提到的这一点(比如canvas的透明度样式并不是用图片哦,而是用css样式,还是从《css揭秘》那本书上学到的)。
当然这个东西或多或少还是有那么一些瑕疵,也存在一些兼容性上的问题,不过对我而言够用就好。
也希望上面介绍的一些东西对您也有收获。
参考:
在博客园里给图片加水印(canvas + drag) - 韩子卢 - 博客园
https://www.cnblogs.com/vvjiang/p/8673879.html
十一、测试题-简答题
1、如何从根本上美化上传控件框(替代思想)?
解答:隐藏上传控件,并加了一个新的按钮在它前面用选择器来触发这个上传控件。
2、通过隐藏上传控件,并加了一个新的按钮在它前面用选择器来触发这个上传控件的方法,怎么拿到上传的文件?
解答:通过event对象,var imgFile = event.target.files[0]; dom中有event,jquery中也有
选择文件后,文件上传控件会触发change事件,此时可以拿到文件。
$('#target_file').change(function (event) {
var imgFile = event.target.files[0];
......
});
3、文件转化为图片的方法?
解答:文件转换为图片实际上首先需要读取文件,这里需要用到FileReader。通过FileReader的readAsDataURL函数读取文件可以获得Base64格式的图片数据,将图片数据赋值给一个Image对象。
4、怎么在图片上加水印?
解答:用canvas来给图片加水印。先将图片用drawImage渲染进canvas,再在指定的位置用fillText渲染文字即可,并将最后的canvas用toDataURL转化为图片数据即可。
5、拖动文字加水印的方法?
解答:在span元素上加drag事件。
当我们设置水印时,直接将文字渲染到canvas上,然后在文字上方安放一个颜色透明的内容为水印文字的span元素。
然后我们在这个span元素上加drag事件。
HTML5拖动功能网上一大堆,这里就不讲了。
6、拖动文字或者图片或者文件用的什么事件?
解答:用的drag事件。
7、因为博客园自动屏蔽了canvas标签和download属性,所以怎么实现在博客里面插入canvas标签和download属性?
解答:可以动态通过js插入。download属性:可以把download属性对应的标签一起插入进去。
// 此处通过这种方式将html插入,是因为博客园自动屏蔽了canvas标签和download属性 var initHtmlConstruct = function () { $('#canvas-container').text('').append('<canvas id="target_canvas" width="100" height="100">浏览器不支持此功能,请升级</canvas><span draggable="true" id="watermark"></span>') $('#toolbar').append('<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>'); }
8、jquery中动态插入一个元素用的方法是什么?
解答:$().append()。 $('#toolbar').append('<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>');