展示demo用一张我家孝敏美美的画报>w<~
介绍下这款基于js和canvas实现的前端马赛克画笔,每次执行步骤都可以撤销,可反复绘制
实现原理分以下几个步骤:
- 将图片导入到canvas中:
var imgObj = new Image();
imgObj.crossOrigin = "Anonymous"; //用于解决图片跨域问题,但在chrome下依旧无效,建议起个node服务或者用safari打开
imgObj.src = 'timg.jpeg';
//待图片加载完后,将其显示在canvas上
imgObj.onload = function(){
context.drawImage(this, 0, 0,canvas.width,canvas.height);//this即是imgObj,保持图片的原始大小
/**
步骤二
*/
}
这里注意下关于图片跨域的报错,可以在网上找些解决方案:http://www.cnblogs.com/haimingpro/p/6098204.html
- 开始处理画笔事件:触发-移动-提笔
var quan = 3; //马赛克的大小
var num = 9; //一次操作包含马赛克的个数
canvas.onmousedown = function(ev){
var ev=ev || window.event;
var dx = ev.clientX-canvas.offsetLeft;
var dy = ev.clientY-canvas.offsetTop;
drawLine(obj,dx,dy); //开始画马塞克
document.onmousemove = function(ev){
var ev = ev || window.event;
var mx = ev.clientX-canvas.offsetLeft;
var my = ev.clientY-canvas.offsetTop;
//当拖拽的距离超过马赛克的直径再画下一个马赛克
if(Math.pow(dx-mx,2)+Math.pow(dy-my,2)>= Math.pow(quan*num,2)){ //
drawLine(obj,mx,my);
dx = mx;
dy = my;
}
};
document.onmouseup = function(){
document.onmousemove = null;
document.onmouseup = null;
};
}
马赛克大小和数量可自定义,马赛克大小越大,那么图像模糊化会越重,数值越小,则越接近原图;两者的数值直接影响画笔的大小。
- 生成马赛克
//原始图像
var originalImgData = context.getImageData(0,0,canvas.width,canvas.height);
var originalPxData = originalImgData.data;
//用于循环修改
var modifyImgData = context.getImageData(0,0,canvas.width,canvas.height);
var modifyPxData = modifyImgData.data;
for(var i=dx-quan*num;i
原理是通过循环找到马赛克区域的每个像素点中心的颜色,将其覆盖到整块像素区域,简单画个草图示意下,马赛克画笔区域默认是正方形:
接下来我们将画笔处理为圆形:
有两种方案:1. 将距离超过马赛克画笔区域半径的像素点过滤掉,如图:
-
直接过滤掉不需要的点,使马赛克画笔接近成圆形
一共要过滤20个点,比较繁琐,但测试了下效果,感觉还是方案二比较好
到这里,我们实现马赛克画笔功能的流程就走完了 最后说下撤销功能
我们只需要在每次绘画之前,先把图像做个保存,存入到缓存数组中,撤销的时候,根据堆栈原理,一步步还原:
//修改缓存
var lastImgArr = [];
canvas.onmousedown = function(ev){
//每次下笔前先保存
lastImgArr.push(context.getImageData(0,0,canvas.width,canvas.height));
}
//撤销修改
document.getElementById('revoked').onclick = function(){
if(lastImgArr && lastImgArr.length){
context.putImageData(lastImgArr.pop(), 0, 0);
}
}
查看完整源码:[github-link]:https://github.com/yomonah/mosaic-js
感谢阅读。