关于原文地址:Canvas在线签名插件插件地址github:https://github.com/javascript-wei/canvas-sign体验预览:Canvas-sign后台最近接到一个临时需求,需要客户方在线签到,然后保存到服务器。功能一般包括撤销(即每笔画需要支持撤销)、更改签名颜色,移动端和PC端都支持。因为急需,当然最好有现成的插件。毕竟,学会偷懒也是一种技能(滑稽)。临时找了一个jSignature第三方签名插件。仔细研究后发现该插件依赖关系复杂。使用这个插件还是需要引入jQuery,因为整个项目不能引入jquery,插件源码也是ES5,甚至是ES3,当时就犹豫了,能不能引入这么复杂的插件因为一个签名。因为这个需求最后只需要保存一张图片到后台,不需要数字证书验证。对于喜欢做的我(完全是被逼的),我可以自己写。因为周五发需求,然后是下周二,看来周末又是默默加班的一天。分析签名是几个操作的集合,从用户手写名字开始,到上传签名图片结束。中间还包括图像处理,比如减少锯齿、撤销、预览等,除了canvas别无选择。从整个交互来看,开始绘制的时候,需要定义起点touchstart(移动端开始)和mousedown(PC端按下鼠标)。为了完成绘图,还需要对手指移动或者鼠标移动进行处理,监听处理两个事件touchmove(移动端),mousemove(PC端)。consthandleMove=(e)=>{this.creat({x:e.clientX-left+0.5,y:e.clientY-top+0.5});}consthandleDown=(e)=>{this.creat({x:e.clientX-left+0.5,y:e.clientY-top+0.5});}constffn={mousedown:handleDown,mousemove:handleMove,//移动touchmove:handleMove,touchstart:handleDown,}draw画线旁边,canvas原生有以下API提供画线:起始路径(beginPath),定位起点(moveTo),移动画笔(lineTo),绘制路径(stroke)有start和move事件,画线的思路很清晰很多,我们需要在button的时候重新设置画笔beginPath按下,并移动画笔moveTo,因为即使按下按钮也是一个完整的绘制过程:consthandleDown=(e)=>{//按下按钮时重置画笔this.ctx.beginPath();//isMouseDown判断按钮是否按下并准备绘制this.isMouseDown=true;constposition={x:e.clientX-left+0.5,y:e.clientY-top+0.5};this.ctx.moveTo(position.x,position.y)this.creat({x:position.x,y:position.y});}移动处理:consthandleMove=(e)=>{//判断鼠标左键是否在pc端按下,移动端不需要做判断if((!this.isMouseDown||e.which!=1)&&!移动)返回;e=移动?e.touches[0]:e;this.creat({x:e.clientX-left+0.5,y:e.clientY-top+0.5});}constcreat=(position={x,y})=>{ctx.lineTo(position.x,position.y);ctx.stroke();}上面代码中的left和top不是内置变量,表示canvas距离屏幕left和top的像素距离,主要用于将屏幕坐标转换为canvas坐标下面是一个获取方法:const{left,top}=this.canvas.getBoundingClientRect();接下来是更改画笔设置,需要支持原生canvas画笔属性://提供条件保存当前样式,用于避免导入json时与现有ctx样式冲突setLineStyle(style={},isSaveLineStyle=true){constctx=this.ctx;constlineStyle=isObject(风格)?{...this.lineStyle,...style}:this.lineStyle;如果(isSaveLineStyle){this.lineStyle=lineStyle;}Object.keys(lineStyle).forEach(key=>{ctx[key]=lineStyle[key];});ctx.beginPath();归还这个;}导出json画线需要路径和画笔的配置,路径是坐标的集合,画笔的配置是setLineStyle时传入的属性。由此可以得到json数据结构:constjson=[{lineStyle:{},position:[]}]什么时候保存,从绘制开始到绘制结束处理json有三种情况:start绘图,绘图和最终绘图。开始绘制:当鼠标按下时,是一个点,此时将psuh的当前值添加到json数组中。绘图:将移动点信息添加到数组中最后一条数据中的位置。结束绘制:不向数组中添加数据,此时保存当前的lineStyle信息。setJson(value,type){constdataJson=this.dataJson;constjsonLength=dataJson.length-1;switch(type){case'moving':dataJson[jsonLength].position.push(value);休息;case'end':dataJson[jsonLength].lineStyle=value;休息;案例“开始”:dataJson.push(value);休息;}}优化为了让移动更流畅,可以考虑requestAnimationFrame优化:constraf=window.requestAnimationFrame;constmove=raf?(e)=>{raf(()=>{handleEvent.handleMove(e);});}:handleEvent.handleMove;写到最后,本文介绍了在线签名实现的主要过程。核心代码可以在这里找到:canvas-sign这道题讨论了这么多内容,你有什么?有问题或者好的想法欢迎参与下方留言评论。
