UNPKG

galaxy-canvas-sign

Version:

银河集团Canvas签名sdk

199 lines (195 loc) 7.48 kB
'use strict'; // 判断是否在移动端 const isMobile = () => 'ontouchstart' in document.documentElement; class SignCanvas { constructor(options) { this.options = options; if (this.options.cropPaddingX === undefined) { this.options.cropPaddingX = 10; } this.isMobile = isMobile(); this.ctx = null; this.currentPoints = []; this.beginPoints = []; this.isPress = false; this.left = 0; this.top = 0; this.canvas = null; this.eventFlag = false; this.once = false; } // 根据配置初始画布 init() { if (this.once === true) { return; } this.once = true; const dom = document.querySelector(this.options.el); if (dom) { const el = document.createElement("canvas"); el.width = this.options.width || 800; el.height = this.options.height || 400; el.style.border = `1px dashed #666`; dom.appendChild(el); if (this.isMobile) { const { left, top } = el.getBoundingClientRect(); this.left = left; this.top = top; } this.canvas = el; this.initCanvas(el); this.addEvents(el); } else { console.error(`Not found node:${this.options.el}`); } return this; } // 初始化画布上下文 initCanvas(canvas) { this.ctx = canvas.getContext('2d'); } // 添加事件 addEvents(canvas) { const eventStart = this.isMobile ? 'touchstart' : 'mousedown'; const eventEnd = this.isMobile ? 'touchend' : 'mouseup'; const eventMove = this.isMobile ? 'touchmove' : 'mousemove'; canvas.addEventListener(eventStart, (e) => { if (this.isMobile) { e = e.touches[0]; } this.isPress = true; // const x:number = e.pageX - this.left + 0.5 // const y:number = e.pageY - this.top + 0.5 const x = this.isMobile ? e.clientX - this.left + 0.5 : e.offsetX + 0.5; const y = this.isMobile ? e.clientY - this.top + 0.5 : e.offsetY + 0.5; this.currentPoints.push([x, y]); this.beginPoints = [x, y]; if (this.isMobile && this.eventFlag === false) { this.eventFlag = true; this.disablePullDownRefresh(); } }); canvas.addEventListener(eventMove, (e) => { const context = this.ctx; if (this.isMobile) { e = e.touches[0]; } if (this.isPress) { // const x = e.clientX - this.left + 0.5 // const y = e.clientY - this.top + 0.5 const x = this.isMobile ? e.clientX - this.left + 0.5 : e.offsetX + 0.5; const y = this.isMobile ? e.clientY - this.top + 0.5 : e.offsetY + 0.5; this.currentPoints.push([x, y]); let endPoint = []; let controlPoint = []; if (this.currentPoints.length > 3) { const lastTwoPoints = this.currentPoints.slice(-2); controlPoint = lastTwoPoints[0]; endPoint = [ (lastTwoPoints[0][0] + lastTwoPoints[1][0]) / 2, (lastTwoPoints[0][1] + lastTwoPoints[1][1]) / 2, ]; } context.beginPath(); context.lineWidth = this.options.lineWidth || 2; context.lineCap = this.options.lineCap || 'round'; context.moveTo(this.beginPoints[0], this.beginPoints[1]); context.quadraticCurveTo(controlPoint[0], controlPoint[1], endPoint[0], endPoint[1]); this.beginPoints = endPoint; context.strokeStyle = this.options.color || '#000'; context.stroke(); } }); canvas.addEventListener(eventEnd, () => { this.isPress = false; if (this.isMobile) { document.querySelector('body').removeEventListener('touchmove', this.pullDownCallback, false); this.eventFlag = false; } }); if (!this.isMobile) { canvas.addEventListener('mouseout', () => { this.isPress = false; }); } } // 解决移动端在画布上touchmove时触发网页下拉操作问题 disablePullDownRefresh() { document.querySelector('body').addEventListener('touchmove', this.pullDownCallback, { passive: false }); } // 阻止下拉 pullDownCallback(e) { e.preventDefault(); } // 清空画布 clear() { this.eventFlag = false; this.currentPoints = []; this.beginPoints = []; this.isPress = false; this.eventFlag = false; this.ctx && this.ctx.clearRect(0, 0, this.options.width, this.options.height); } // 判断点信息是否为空 getPoints() { return this.currentPoints; } // 获取当前截图 exportCanvas() { if (this.options.crop) { const offCanvas = this.cropRange(); return offCanvas; } else { return this.canvas; } } cropRange() { const imageData = this.ctx.getImageData(0, 0, this.options.width, this.options.height); const len = imageData.data.length; const obj = { xmin: 0, xmax: 0, ymin: 0, ymax: 0 }; let flag = false; for (let i = 0; i < len; i += 4) { const y = Math.floor((i + 3) / (this.options.width * 4)); const x = (((i + 4) / 4) % this.options.width); if (imageData.data[i + 3] !== 0) { // 代表笔画点 if (flag === false) { obj.xmin = x; obj.xmax = x; obj.ymin = y; obj.ymax = y; flag = true; } if (x < obj.xmin) { obj.xmin = x; } if (x > obj.xmax) { obj.xmax = x; } if (y < obj.ymin) { obj.ymin = y; } if (y > obj.ymax) { obj.ymax = y; } } } const offCanvas = document.createElement("canvas"); const cropPaddingX = this.options.cropPaddingX !== undefined ? this.options.cropPaddingX : 10; const cropPaddingY = this.options.cropPaddingY !== undefined ? this.options.cropPaddingY : 10; offCanvas.width = (obj.xmax - obj.xmin) + 2 * cropPaddingX; offCanvas.height = (obj.ymax - obj.ymin) + 2 * cropPaddingY; const offCtx = offCanvas.getContext("2d"); if (this.canvas && offCtx) { offCtx.drawImage(this.canvas, obj.xmin, obj.ymin, obj.xmax - obj.xmin, obj.ymax - obj.ymin, cropPaddingX, cropPaddingY, obj.xmax - obj.xmin, obj.ymax - obj.ymin); } return offCanvas; } } module.exports = SignCanvas;