300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Canvas画板涂鸦生成图片

Canvas画板涂鸦生成图片

时间:2024-06-25 03:18:02

相关推荐

Canvas画板涂鸦生成图片

笔者从事教育软件行业,担任公司的前端开发,产品主要应用于PC端和移动端。之前遇到一个需求:老师在课堂上发布一张习题图片给学生练习的时候,学生要在移动端上接受老师发的图片,并在上面写出答案提交,然后老师接收到这张图片,又可以在上面批改。

具体实现的需求是这样的:学生收到老师发的图片,就直接在学会设备(学生使用的是订做的有管控系统的平板)上显示,

学生点击答题按钮或者是直接点击图片,就开始在图片上画写,功能上,我们要给学生画笔多颜色,笔画多粗细,还要有

橡皮擦的功能。我之前的办法是直接把老师发的图片复制到canvas上,但是使用画笔会把原来的图片擦掉,这个不符合要求,

后面我就改成了使用两个canvas层叠的方法实现了。老师下发的图片在最底层,然后在这个底层的上面覆盖一个canvas,

这个canvas要复制图片上的内容,并且还要保存复制那个图片的高宽给canvas设置上,其实这一层就是给画板做背景的,

然后再这个画板上面还要加一层canvas,这一层是提供给学生画画的,同样要设置一样的高宽,布局上要使用绝对定位,使两个

canvas完全重叠在一起,这样做的目的是为了使用橡皮的时候,背景图不会被擦掉,最后把两个canvas融合到一起就搞定了,下面上代码;

css样式部分

*{margin: 0;padding: 0;}HTML,body{width: 100%;height: 100%;overflow: hidden;}.canvasdiv{width: 100%;height: 100%;position: absolute;display: none;z-index: 5;top: 0;left: 0;background: #DADADA;overflow: hidden;-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}.navbar{width: 500px;height: 40px;margin: 5px 0;position: relative;}.navbar a{display: inline-block;height: 40px;width: 40px;border-radius: 20px;position: absolute;right: -20px;background: #B4A484;text-align: center;line-height: 40px;font-size: 30px;top: 0;-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}.eraseSeries{display: inline-block;height: 20px;margin: 10px 0 10px 15px;vertical-align: middle;display: none;}.eraseSeries input{width: 20px;height: 20px;vertical-align: middle;}select,.erase,.etext,.saveimg,.cancelimg{height: 30px;margin: 5px 0px 5px 15px;vertical-align: middle;}.erase,.etext,.saveimg,.cancelimg{padding: 0 10px;}textarea{width: 200px;height: 30px;background: transparent;position: absolute;display:none;top: 50px;left: 0;/*outline:none;*/border: 2px solid #c1c1c1;resize:both;}#eraseImg {border: solid;color: gray;border-radius: 118px;width: 5px;height: 5px;position: absolute;display: none;}.bottomCanvas{position: relative;left: 0;top: 0;z-index: 1;}.centerCanvas{background: transparent;position: absolute;left: 0;top: 50px;z-index: 2;display: none;}.topCanvas{background: transparent;position: absolute;left: 0;top: 50px;z-index: 3;display: none;}.drag{z-index: 4;}

HTML部分

<!--zhuo599 下面这个img是老师发过来的图片,也就是准备在上面画的底图--><img src="g.jpg" class="img" id="imgsrc" /><div class="canvasdiv" id="canvasdiv"><div class="navbar" id="btnTeam"><!--zhuo599 画笔颜色设置--><select id="color"><option class="opt" value="red">红色</option><option class="opt" value="yellow">黄色</option><option class="opt" value="blue">蓝色</option><option class="opt" value="black" selected>黑色</option><option class="opt" value="green">绿色</option></select><select id="fontSize"><!--zhuo599 画笔大小--><option value="5" selected>5</option><option value="10">10</option><option value="15">15</option><option value="20">20</option><option value="30">30</option></select><button id="erase" class="erase">擦皮</button><!--zhuo599 橡皮按钮--><div class="eraseSeries" id="eraseSeries"><!--zhuo599 橡皮大小--><input type="radio" name="eraseSize" value="5" checked="checked" />5<input type="radio" name="eraseSize" value="10" />10<input type="radio" name="eraseSize" value="15" /> 15<input type="radio" name="eraseSize" value="20" /> 20<input type="radio" name="eraseSize" value="30" />30</div><button id="etext" class="etext">文字</button><button id="saveimg" class="saveimg" onclick="saveImg()">保存</button><button id="cancel" class="cancelimg" onclick="cancelImg()">取消</button></div><canvas id="myCanvas" class="bottomCanvas"></canvas><canvas id="myCanvas3" class="topCanvas"></canvas><div id="eraseImg"><!--zhuo599 橡皮形状--></div><textarea id="textareaInput" class="drag"></textarea></div><img src="" id="tupian" />

JavaScript部分

var sizeE;//橡皮擦大小var fontSize;//笔画 字体大小var allColor; //颜色var mousePress = false;//画笔开关var last = null;var capi = false;//擦皮开关var inText = false;//文本框开关var ziX,ziY;//文字具体位置var canvas = document.querySelector("#myCanvas");var cxt = canvas.getContext("2d");//var canvas2 = document.getElementById('myCanvas2');var canvas3 = document.getElementById('myCanvas3');/*zhuo599 第一步点击图片生成两个canvas层 start*/var imgsrc = document.getElementById("imgsrc");function imgTest(){var ele = this;document.getElementById("canvasdiv").style.display = "block";//canvas2.style.display = "block";console.log(ele.clientWidth,ele.clientHeight);canvas3.style.display = "block";canvas3.width = ele.clientWidth;canvas3.height = ele.clientHeight;canvas.width= ele.clientWidth;canvas.height= ele.clientHeight;cxt.drawImage(ele, 0, 0, ele.clientWidth, ele.clientHeight);}imgsrc.onclick = imgTest;imgsrc.addEventListener("touchstart",imgTest,false);/* 第一步点击图片生成两个canvas层 end*//*zhuo599 第二步更改橡皮大小 start*/var eraseImg = document.getElementById("eraseImg");var size = document.getElementsByName("eraseSize");function caPi(){for (var i = 0; i < size.length; i++) {//获取到橡皮单选按钮组的选中值 if (size[i].checked == true) {sizeE = size[i].value; //将该值传到全局变量上,sizeE需要用来控制橡皮样式的位置 eraseImg.style.width = size[i].value +"px";//橡皮样式大小发生改变 eraseImg.style.height = size[i].value +"px";}}}/* 第二步更改橡皮大小 end*//*zhuo599 第三步更改大小 start*/var fontS = document.getElementById("fontSize");function fnFontsize(){fontSize = document.getElementById("fontSize").value;}fontS.onchange = fnFontsize;fontS.addEventListener("touchstart",fnFontsize,false);/* 第三步更改大小 end*//*zhuo599 第四步更改颜色 start*/var color = document.getElementById("color");function fnColor(){allColor = document.getElementById("color").value;}color.onchange = fnColor;color.addEventListener("touchstart",fnColor,false);/* 第四步更改颜色 end*//*zhuo599 第五步 擦皮画笔变换 start*/var erase = document.getElementById("erase");var eraseSeries = document.getElementById("eraseSeries");function penRubber(e){if(erase.innerText == "擦皮"){eraseSeries.style.display = "inline-block";erase.innerText = "画笔";capi = true;}else{eraseSeries.style.display = "none";erase.innerText = "擦皮";capi = false;}e.preventDefault();}erase.onclick = penRubber;erase.addEventListener("touchstart",penRubber,false);/* 第五步 擦皮画笔变换 end*/fnFontsize();//页面刚进入初始化字体大小fnColor();//页面刚进入初始化颜色caPi();//初始化擦皮大小/*zhuo599 第六步 定位文字输入框的位置,并将文字画到canvas上 start*/var board = canvas3.getContext('2d');var textInput = document.getElementById("textareaInput");function beginDraw() {mousePress = true;caPi();//拿到擦皮的大小if(inText){//如果文本框的开关是打开的,那么在点击canvas3的时候会出现一个文本框用来输入文字mousePress = false;//文本框开启的时候关闭画笔功能var event = window.event||event;if(isTouch(event)) {x = event.touches[0].pageX;y = event.touches[0].pageY;//console.log("手机"+x+",,,"+y);} else {x = event.offsetX + event.target.offsetLeft;y = event.offsetY + event.target.offsetTop;}textInput.style.display = "inline-block";textInput.style.left = x+"px";textInput.style.top = y+"px";ziX = x;ziY = y;//保存位置,为文字显示提供具体位置console.log(ziX,ziY);inText = false;//用完关闭文本框开关var type = event.type;if(type.indexOf('touch') >= 0) {//说明是手机事件,需要阻止冒泡event.preventDefault();}}else{writeZi();}}function writeZi(){console.log("画出文字了",ziX,ziY);if(ziX != undefined && ziY != undefined){board.font = fontSize+"px 宋体";board.fillStyle = allColor;board.fillText(textInput.value,ziX+2,ziY-36);textInput.style.display = "none";textInput.style.top = "50px";textInput.style.left = "0px";textInput.value = "";}}textInput.onblur = writeZi;/* 第六步 定位文字输入框的位置,并将文字画到canvas上 end*//*zhuo599 第七步 画笔橡皮擦切换 start*/function drawing() {board.lineWidth = fontSize;//全局画笔宽度if(!capi){//画笔console.log(fontSize,allColor);board.strokeStyle = allColor;//console.log(fontSize,allColor);var event = window.event||event;event.preventDefault();if(!mousePress) return;var xy = pos(event);if(last != null) {board.beginPath();board.lineCap="round";board.moveTo(last.x, last.y);board.lineTo(xy.x, xy.y);board.stroke();}last = xy;}else{//橡皮var event = window.event||event;event.preventDefault();if(!mousePress) return;var xy = pos(event);if(last != null) {board.clearRect(xy.x, xy.y, sizeE, sizeE);}last = xy;}}/* 第七步 画笔橡皮擦切换 end*//*zhuo599 阻止事件冒泡和确定需要画写的位置 start*/function endDraw() {var event = window.event||event;mousePress = false;event.preventDefault();last = null;}function pos(event) {var x, y;if(isTouch(event)) {x = event.touches[0].pageX;y = event.touches[0].pageY-50;//console.log("手机"+x+",,,"+y);} else {x = event.offsetX + event.target.offsetLeft;y = event.offsetY + event.target.offsetTop-50;}// log('x='+x+' y='+y);return {x: x,y: y};}function isTouch(event) {var type = event.type;//console.log(type);if(type.indexOf('touch') >= 0) {return true;} else {return false;}}canvas3.onmousedown = beginDraw;canvas3.onmousemove = drawing;canvas3.onmouseup = endDraw;canvas3.addEventListener('touchstart', beginDraw, false);canvas3.addEventListener('touchmove', drawing, false);canvas3.addEventListener('touchend', endDraw, false);/* 阻止事件冒泡和确定需要画写的位置 end*//*zhuo599 第八步在topCanvas层上点击出文本框 start*/var inputText = document.getElementById("etext");function displayInput(){inText = true;}inputText.onclick = displayInput;inputText.addEventListener('touchstart', displayInput, false);/* 第八步在topCanvas层上点击出文本框 end*//*** vizhuowd* 保存图片方法*/function saveImg(){cxt.drawImage(canvas3, 0, 0, 639, 640);//base64var dataUrl = canvas.toDataURL();document.getElementById("tupian").src = dataUrl;}/*** vizhuowd* 取消方法*/function cancelImg(){board.clearRect(0, 0, canvas3.width, canvas3.height);document.getElementById("canvasdiv").style.display = "none";canvas3.style.display = "none";}

PS:最开始是只支持PC端的,后面又加入了移动端的操作,一个小demo,自己在这里保存一下,也欢迎各位开发者一起互相学习讨论。这个东西后面放到正式版本中,有很多东西是要调的,我后面自己又加了文本框输入的功能,比较low,选择文本框那里要改,文字多了会超出图片范围,初始话时字体要调大,位置也要改,哈哈

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。