移動端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>
實現效果: