canvas实现移动端画笔功能
移动端touch事件有以下几个属性
- ClientX Y 相对于视口的坐标
- pageX Y 相对于页面左上角原点的坐标
- screenX Y 相对于屏幕的坐标标
- movementX Y 相对于上一次坐标的坐标
然而就是没有offset X Y
实现方法:
- 获得触摸点的pageX Y
- 通过offsetTop left计算元素左上角的顶点位置
- 计算相对坐标
代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canvas画笔</title> <style> html, body { width: 100%; height: 100%; } * { margin: 0; padding: 0; } #canvas { position:relative; top: 10%; left: 5%; width: 90%; height: 80%; } #canvas canvas { display: block; } #clearCanvas, #saveCanvas { position: absolute; bottom: 0; z-index: 1; width: 50%; height: 60px; border: 1px solid #dedede; line-height: 60px; text-align: center; } #clearCanvas { left: 0; } #saveCanvas { right: 0; } .errorCanvas { width: 100%; height: 100%; text-align: center; transform: translateY(40%); } </style> <script> window.onload = function () { new lineCanvas({ el: document.querySelector('#canvas'), clearEl: document.querySelector('#clearCanvas'), saveEl: document.querySelector('#saveCanvas'), // lineWidth: 1, // 线条粗细 color: '#0000ff', // 线条颜色 lineShadowColor: '#0000ff', // 线条阴影颜色 // background: '#fff' }); } function lineCanvas(obj) { this.lineWidth = 5; this.color = '#000'; // 线条颜色 this.lineShadowColor = '#000'; //线条阴影颜色 this.shadowBlur = 1; //线条阴影大小 this.background = '#fff'; // 获取元素相对于body的offsetTop 和 offsetLeft this.offsetLeft_body = getOffsetTopByBody(obj.el)[0]; this.offsetTop_body = getOffsetTopByBody(obj.el)[1]; for (var i in obj) { this[i] = obj[i]; }; this.canvas = document.createElement('canvas'); if (!(this.canvas.getContext && this.canvas.getContext('2d'))) { this.section = document.createElement('section'); this.section.className = 'errorCanvas'; this.section.innerHTML = '对不起,当前浏览器暂不支持此功能!' this.el.prepend(this.section); return } this.canvas.width = this.el.clientWidth; this.canvas.height = this.el.clientHeight; this.el.prepend(this.canvas); this.cxt = this.canvas.getContext('2d'); this.cxt.fillStyle = this.background; this.cxt.fillRect(0, 0, this.canvas.width, this.canvas.height); this.cxt.strokeStyle = this.color; this.cxt.lineWidth = this.lineWidth; this.cxt.lineCap = 'round'; // 线条末端添加圆形线帽,减少线条的生硬感 this.cxt.lineJoin = 'round'; // 线条交汇时为原型边角 // 利用阴影,消除锯齿 this.cxt.shadowBlur = this.shadowBlur; this.cxt.shadowColor = this.lineShadowColor; // 开始绘制 this.canvas.addEventListener('touchstart', function (e) { this.cxt.beginPath(); this.cxt.moveTo(e.changedTouches[0].pageX-this.offsetLeft_body, e.changedTouches[0].pageY-this.offsetTop_body); }.bind(this), false); // 绘制中 this.canvas.addEventListener('touchmove', function (e) { this.cxt.lineTo(e.changedTouches[0].pageX-this.offsetLeft_body, e.changedTouches[0].pageY-this.offsetTop_body); this.cxt.stroke(); }.bind(this), false); // 结束绘制 this.canvas.addEventListener('touchend', function (e) { this.cxt.closePath(); }.bind(this), false); // 清除画布 this.clearEl.addEventListener('click', function () { this.cxt.clearRect(0, 0, this.canvas.width, this.canvas.height); }.bind(this), false); // 保存图片 this.saveEl.addEventListener('click', function () { var imgBase64 = this.canvas.toDataURL(); var imgPng = this.canvas.toDataURL('image/png'); var imgJpg = this.canvas.toDataURL('image/jpeg', 0.8); console.log(imgPng); }.bind(this), false); // 获取元素相对于body的offsetTop 和 offsetLeft function getOffsetTopByBody (el) { let offsetTop = 0 let offsetLeft = 0 while (el && el.tagName !== 'BODY') { offsetTop += el.offsetTop offsetLeft+= el.offsetLeft el = el.offsetParent } return [offsetLeft,offsetTop] } } </script> </head> <body> <div id="canvas"> <p id="clearCanvas">清除</p> <p id="saveCanvas">保存</p> </div> </body> </html>
实现效果: