最近有个需求,利用h5的canvas对图片一些涉及个人隐私的地方进行打码再上传,而且最好能实现批量打码.意思是在一张图片上对哪些地方做了打码,后续的所有图片都在同样的地方也可以自动打上码,不用人工一张一张进行图片涂抹了.
例如:
首先想到的是利用canvas的drawImage方法将图片加载进来,然后在利用鼠标的点击移动事件在画布上面划线,很容易就实现了这个功能.但是当载入其他图片的时候,之前画的线就全部消失了,因为canvas使用drawImage方法后会清空画布,所以这个方法只能对一张图片进行打码.
后来就琢磨能不能将图片和涂鸦分开,不放在一个canvas里面,将两个canvas重叠起来,大小一样,暂时设定为canvas1和canvas2,canvas1在底层,用于载入图片的容器,canvas2在上层,用于用户的涂抹层,当用户在canvas2上面进行涂抹的时候,因为canvas1和canvas2是完全重叠的,看起来就像是在图片上涂抹一样,涂抹完成之后,用户点击保存按钮时,将canvas2转化为image对象,然后使用canvas1的drawImage的方法将这个image对象加载近canvas1,于是canvas1就成了两个canvas的结合画面,然后在将canvas1转为image对象保存起来即可,因为现在canvas2的画布还没有被清空,此时我们只需要在canvas1载入另外一张图片,在点击保存又能对这张图片进行一模一样的打码工作了,后续只需要将所有需要打码的图片放入一个数组,利用for循环就能够实现批量图片打码的工作了.
但是此方法对于所有的图片的要求是大小必须一样,因为项目对于打码的图片大都是来自于手机截图,图片大小都是一样的,所以这个方法完全可以胜任此工作.
下面贴上源码
js代码
function Doodle() { this.mousePressed = false;//鼠标是否按下 this.imgWidth = 300; this.imgHeight = ""; this.lastX; this.lastY; this.cPushArray = [];//存储画布仓库 this.cStep = -1;//当前步数 this.c1;// 图片画布 this.ctx1;//canvas对象1 this.c2;//涂鸦画布 this.ctx2;//canvas对象2 this.importMuban = function(imgUrl) {//载入模板图片,以此图片的宽高比例来对后面所有的图片做预设. var self = this; var image = new Image(); image.src = imgUrl; $(image).load(function () { self.imgHeight = (300/image.width)*image.height; self.c1.height = self.imgHeight; self.c2.height = self.imgHeight; $(".canvas-box").css({ 300, height: self.imgHeight }); self.ctx1.drawImage(image, 0, 0, self.imgWidth, self.imgHeight); }); }; this.importImg = function(imgUrl) {//载入其他图片 var self = this; var image = new Image(); image.src = imgUrl; $(image).load(function () { self.ctx1.drawImage(image, 0, 0, self.imgWidth, self.imgHeight); }); }; this.saveImg = function() {//保存图片 var self = this; var newImg = this.c2.toDataURL("image/png"); var Img = new Image(); Img.src = newImg; $(Img).load(function (){ self.ctx1.drawImage(Img, 0, 0, self.imgWidth, self.imgHeight); var img = self.c1.toDataURL("image/png"); var ele = document.createElement("img"); ele.src = img; document.body.appendChild(ele); }); }; this.clearCanvas = function () {//清空画布 this.ctx2.clearRect(0,0,this.c1.width,this.c1.height); }; this.Draw = function (x, y, isDown) { if (isDown) { this.ctx2.beginPath(); this.ctx2.strokeStyle = $('#selColor').val(); this.ctx2.lineWidth = $('#selWidth').val(); this.ctx2.lineJoin = "round"; this.ctx2.moveTo(this.lastX, this.lastY); this.ctx2.lineTo(x, y); this.ctx2.closePath(); this.ctx2.stroke(); } this.lastX = x; this.lastY = y; }; this.cPush = function() { this.cStep++; if (this.cStep < this.cPushArray.length) { this.cPushArray.length = this.cStep; } this.cPushArray.push(document.getElementById('myCanvas2').toDataURL()); }; this.cUndo = function() { var self = this; if (self.cStep > 0) { self.cStep--; var canvasPic = new Image(); canvasPic.src = self.cPushArray[self.cStep]; canvasPic.onload = function () { console.log(self.cStep,self.cPushArray); self.ctx2.clearRect(0,0,self.c1.width,self.c1.height); self.ctx2.drawImage(canvasPic, 0, 0, self.imgWidth, self.imgHeight); } } }; this.cRedo = function() { var self = this; if (self.cStep < self.cPushArray.length-1) { self.cStep++; var canvasPic = new Image(); canvasPic.src = self.cPushArray[self.cStep]; canvasPic.onload = function () { self.ctx2.clearRect(0,0,self.c1.width,self.c1.height); self.ctx2.drawImage(canvasPic, 0, 0, self.imgWidth, self.imgHeight); } } }; this.initFn = function (cId1,cId2){ var self = this; this.c1 = $(cId1)[0]; this.c2 = $(cId2)[0]; this.ctx1 = this.c1.getContext("2d"); this.ctx2 = this.c2.getContext("2d"); this.cPush(); $(cId2).mousedown(function (e) { self.mousePressed = true; self.Draw(e.pageX - $(this).offset().left, e.pageY - $(this).offset().top, false); console.log("anxia") }); $(cId2).mousemove(function (e) { if (self.mousePressed) { self.Draw(e.pageX - $(this).offset().left, e.pageY - $(this).offset().top, true); } }); $(cId2).mouseup(function (e) { if (self.mousePressed) { self.mousePressed = false; self.cPush(); } }); $(cId2).mouseleave(function (e) { if (self.mousePressed) { self.mousePressed = false; self.cPush(); } }); } } $(function (){ var aDoodle = new Doodle(); aDoodle.initFn("#myCanvas1","#myCanvas2"); $("#img1").click(function (){ aDoodle.importMuban("img/1.jpg"); }); $("#img2").click(function (){ aDoodle.importImg("img/2.jpg"); }); $("#img3").click(function (){ aDoodle.importImg("img/3.jpg"); }); $("#img4").click(function (){ aDoodle.importImg("img/4.jpg"); }); $("#img5").click(function (){ aDoodle.importImg("img/5.jpg"); }); $("#undo").click(function (){ aDoodle.cUndo(); }); $("#redo").click(function (){ aDoodle.cRedo(); }); $("#clearDraw").click(function (){ aDoodle.clearCanvas(); }); $("#saveImg").click(function (){ aDoodle.saveImg(); }); })
html代码:
<!doctype html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <script src="js/jquery-1.7.2.min.js" type="text/javascript"></script> <script type="text/javascript" src="js/doodle.js"></script> <style type="text/css"> select{color: #333;} .htmleaf-icon{color: #fff;} .canvas-box{ width: 500px; height: 400px; margin: 0 auto; background-size: cover; background-repeat: no-repeat; border: 1px solid #ccc; position: relative; } #myCanvas1{ position: absolute; top: 0px; left: 0px; } #myCanvas2{ position: absolute; top: 0px; left: 0px; z-index: 3; } .htmleaf-content{ text-align: center; } </style> </head> <body> <div class="htmleaf-container"> <div class="htmleaf-content bgcolor-3"> <div align="center" id="bgImg" class="canvas-box"> <canvas id="myCanvas1" width="300"></canvas> <canvas id="myCanvas2" width="300"></canvas> </div> <button class="btn btn-primary" id="clearDraw">清空画布</button> 线条宽度 : <select id="selWidth"> <option value="1">1</option> <option value="3">3</option> <option value="5">5</option> <option value="7">7</option> <option value="9" selected="selected">9</option> <option value="11">11</option> </select> 线条颜色 : <select id="selColor"> <option value="black">黑色</option> <option value="blue" selected="selected">蓝色</option> <option value="red">红色</option> <option value="green">绿色</option> <option value="yellow">黄色</option> <option value="gray">灰色</option> </select> <button class="btn btn-primary" id="undo">上一步</button> <button class="btn btn-danger" id="redo">下一步</button> <button id="saveImg" id="saveImg">保存图片</button> </div> <div style="text-align:center;"> <button id="img1">载入模板图</button> <button id="img2">图片1</button> <button id="img3">图片2</button> <button id="img4">图片3</button> <button id="img5">图片4</button> </div> </div> </body> </html>
我在此方法的基础上又添加了改变线的像素和颜色的功能.