了解更多开源请访问:开源基础软件社区https://ost.51cto.com介绍这是一个画板,我们可以实现简单的绘画。功能包括:画笔颜色切换、清除、橡皮擦、保存、退出、反回缩效果显示原理分析1.线条生成这是最基本的功能。具体的实现方法在之前的文章中也有介绍。.首先,我们需要在触摸移动事件中绑定画布上下文对象,因为我们是通过触摸生成相应的线条。然后,定义两个数组,分别存储鼠标的x和y坐标,当鼠标按下时开始记录,当鼠标移动时将坐标压入数组。最后通过drawing方法绘制获取到的坐标,通过moveTo和lineTo进行绘制得到直线。//绘图函数lineDraw(e){this.ctx.lineWidth=this.lineWidththis.ctx.strokeStyle=this.strokeStylethis.ctx.beginPath()//将圆形线帽添加到线条的每一端。this.ctx.lineCap='round'//每次取出数组中的最后一个值作为起点this.ctx.moveTo(this.ArrX[this.ArrX.length-1],this.ArrY[this.ArrY.length-1])this.ctx.lineTo(e.touches[0].localX,e.touches[0].localY)this.ctx.stroke()}2。清除画板和清除画布的功能最简单,调用canvasAPI的ctx.clearRect即可。API介绍:clearRect(x:number,y:number,w:number,h:number):void。x:指定矩形左上角的x坐标。y:指定矩形左上角的y坐标。width:指定矩形的宽度。height:指定矩形的高度。因为这里清空,所以只需要设置坐标到左上角,然后设置宽高和当前画布的宽高一致,就可以清空画板了。//width和height为获取的画布宽高clearBtn(e){this.ctx.clearRect(0,0,this.width,this.height);}3.这里橡皮擦的实现其实和清空画板是一样的,只是橡皮擦清空的面积小了很多。首先定义一个flag来判断是否需要橡皮擦功能,用户可以通过点击下面的橡皮擦图片来控制。然后,我们需要提前判断触摸移动事件中是否需要橡皮擦功能。如有必要,我们将画线功能替换为橡皮擦功能。功能实现的API与清空画板相同。最后,还有橡皮擦大小的问题。我们可以预先定义一个属性来控制大小。在橡皮擦功能中,只需添加此属性即可。touchmove(e){if(this.isEraser){this.ctx.clearRect(this.ArrX[this.ArrX.length-1]-this.eraserValue,this.ArrY[this.ArrY.length-1]-this.橡皮擦值,this.eraserValue,this.eraserValue)}else{this.lineDraw(e)}this.ArrX.push(e.touches[0].localX)this.ArrY.push(e.touches[0].localY)}4.保存绘图还没有实现。这里用到了canvas的一个API:toDataURL(type?:string,quality?:number)。可以生成包含图像显示的URL。参数:type:可选参数,用于指定图片格式,默认格式为image/png。quality:当指定的图片格式为image/jpeg或image/webp时,可以从0到1中选择图片的质量,如果超出取值范围,将使用默认值0.92。返回值:字符串:图片的URL地址。我们可以通过toDataURL存储获取图片的URL地址,在需要的地方生成canvas图片。saveBtn(){constel=this.$refs.canvas;constdataURL=el.toDataURL();控制台日志(数据URL);}5.Withdraw提现功能使用了很多API,需要耐心阅读文档。在实现retract函数之前,我们需要将每次绘制的线条进行存储。在鼠标弹起事件中,会通过toDataURL()获取当前图片,压入数组,存储。实现撤销功能:首先,我们需要一个属性:步频。我们每画一条线段,步长就会自动增加。在undo函数中,我们只需要将当前步幅频率设置为-1,就可以得到上次绘制的图像。然后,通过clearRect清除当前图像。最后获取最后一张图片,通过onload函数绘制图片,通过drawImage实现绘制功能。6.反撤回反撤回的实现与撤回基本相同,只是获取的图像不同。和提款一样,每次都需要获取图片,这里可以直接使用提款时获取的图片。实现防脱功能:首先,每次防脱,我们需要增加步频++,可以得到当前显示人像的上一张人像。然后,通过clearRect清除当前图像。最后获取最后一张图片,通过onload函数绘制图片,通过drawImage实现绘制功能。7.线条样式线条颜色的实现比较简单。当用户点击想要的颜色样式时,只要修改画布的ctx.strokeStyle即可。完整代码index.js://@ts-nocheckexportdefault{data:{ctx:'',width:0,height:0,ArrX:[],ArrY:[],lineWidth:14,isEraser:false,//是否启用橡皮擦功能eraserValue:30,//橡皮擦大小strokeStyle:'black',canvasHistory:[],step:-1,showClear:true,showEraser:true,showSave:true,showUndo:true,showRedo:true},onLayoutReady(){constel=this.$refs.canvas;this.ctx=el.getContext('2d')this.width=el.getBoundingClientRect().width;this.height=el.getBoundingClientRect().height;},//偏移很多touchstart(e){this.ArrX.push(e.touches[0].localX)this.ArrY.push(e.touches[0].localY)if(this.isEraser){this.ctx.clearRect(e.touches[0].localX-this.eraserValue,e.touches[0].localY-this.eraserValue,this.eraserValue,this.eraserValue)}},touchmove(e){如果(这.isEraser){this.ctx.clearRect(this.ArrX[this.ArrX.length-1]-this.eraserValue,this.ArrY[this.ArrY.length-1]-this.eraserValue,this.eraserValue,this.eraserValue)}else{this.lineDraw(e)}this.ArrX.push(e.touches[0].localX)this.ArrY.push(e.touches[0].localY)},lineDraw(e){this.ctx.lineWidth=this.lineWidththis.ctx.strokeStyle=this.strokeStylethis.ctx.beginPath()//向线条的每个末端添加圆形线帽this.ctx.lineCap='round'//每次取出数组中的最后一个值作为起点this.ctx.moveTo(this.ArrX[this.ArrX.length-1],this.ArrY[this.ArrY.length-1])this.ctx.lineTo(e.touches[0].localX,e.touches[0].localY)this.ctx.stroke()},touchend(e){constel=this.$refs.canvas;这一步++;this.canvasHistory.push(el.toDataURL());//添加新绘图到历史记录console.log(this.step)},saveBtn(){constel=this.$refs.canvas;constdataURL=el.toDataURL();控制台日志(数据URL);},withdraw(){this.ArrX.pop()this.ArrY.pop()},clearBtn(e){this.ctx.clearRect(0,0,this.width,this.height);this.showClear=falsethis.showEraser=truethis.showSave=truethis.showUndo=truethis.showRedo=true},clearBtnEnd(){this.showClear=true},EraserBtn(){this.isEraser=!this.isEraserthis.showClear=truethis.showEraser=!this.showEraserthis.showSave=truethis.showUndo=truethis.showRedo=true},saveBtn(){this.showClear=truethis.showEraser=truethis.showSave=falsethis.showUndo=true这.showRedo=true},saveBtnEnd(){this.showClear=truethis.showEraser=truethis.showSave=truethis.showUndo=truethis.showRedo=true},red(){this.strokeStyle='red'},blue(){this.strokeStyle='blue'},white(){this.strokeStyle='white'},black(){this.strokeStyle='black'},undo(){if(this.step>=0){这一步--;this.ctx.clearRect(0,0,this.width,this.height);让img=newImage();img.src=this.canvasHistory[this.step];letthat=thisimg.onload=function(){//画上图片that.ctx.drawImage(canvasPic,0,0);};}else{console.log('不能再继续营销了');}this.showClear=truethis.showEraser=truethis.showSave=truethis.showUndo=falsethis.showRedo=true},undoEnd(){this.showClear=truethis.showEraser=truethis.showSave=truethis.showUndo=truethis.showRedo=true},redo(){if(this.step
