From 3b03f87a02458f719e2eb4bf112a13441b427d14 Mon Sep 17 00:00:00 2001 From: ‘chensiAb’ <‘chenchenco03@163.com’> Date: Tue, 25 Mar 2025 13:54:34 +0800 Subject: [PATCH] Merge branch 'master' of ssh://dev.zhiheiot.com:29418/mob-components --- forms/userSignature/CSignatureLayer.vue | 227 ++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 145 insertions(+), 82 deletions(-) diff --git a/forms/userSignature/CSignatureLayer.vue b/forms/userSignature/CSignatureLayer.vue index 23f6766..b5d71d1 100644 --- a/forms/userSignature/CSignatureLayer.vue +++ b/forms/userSignature/CSignatureLayer.vue @@ -8,7 +8,7 @@ class="c-signature-layer" title="手写板 / 请书写签名" :isOpened="layerOpened" - :onClose="evt => null" + :onClose="evt => handleClose()" > <view class="c-signature-layer-draw"> <view class="size-box-top"></view> @@ -16,10 +16,10 @@ <canvas class="drawing" ref="drawing" - :canvasId="cavId" - :width="cavWidth" - :height="cavHeight" + type="2d" + :id="cavId" :disableScroll="true" + v-if="cavShow" @touchstart="evt => handleWriteStart(evt)" @touchmove="evt => handleWriteMove(evt)" @touchend="evt => handleWriteEnd(evt)" @@ -45,8 +45,8 @@ import Taro from '@tarojs/taro'; import { $ } from '@tarojs/extend'; import { AtFloatLayout, AtButton } from 'taro-ui-vue'; -import './cSignatureLayer.scss'; import { Tools } from '@components/common/Tools'; +import './cSignatureLayer.scss'; export default { name: 'CSignatureLayer', @@ -59,8 +59,7 @@ return { cavId: 'signCanvas-' + Date.now() + '-' + parseInt(Math.random() * 10000), layerOpened: false, - cavWidth: 0, - cavHeight: 0, + cavShow: false, curPoint: {}, lastPoint: {}, curLine: [], @@ -70,26 +69,63 @@ chirography: [], // 初始画圆的半径 radius: 1, + canvasContext: null, }; }, methods: { + _initDraw() { + const query = Taro.createSelectorQuery(); + query + .select(`#${this.cavId}`) + .fields({ node: true, size: true }) + .exec(res => { + // Canvas 对象 + const canvas = res[0].node; + // Canvas 画布的实际绘制宽高 + const renderWidth = res[0].width; + const renderHeight = res[0].height; + // Canvas 绘制上下文 + this.canvasContext = canvas.getContext('2d'); + this.canvas = canvas; + // 初始化画布大小 + const dpr = Taro.getSystemInfoSync().pixelRatio; + canvas.width = renderWidth * dpr; + canvas.height = renderHeight * dpr; + this.canvasContext.scale(dpr, dpr); + // 初始化变量 + this.handleRestDraw(); + }); + }, $onDraw(callback) { this.layerOpened = true; this._callback = callback; - this.handleRestDraw(); + this.$nextTick(() => { + setTimeout(() => { + this.cavShow = true; + setTimeout(() => { + this._initDraw(); + }, 100); + }, 300); + }); }, handleRestDraw() { this.firstTouch = true; this.curLine = []; this.chirography = []; - this.canvasContext.clearRect(0, 0, this.cavWidth, this.cavHeight); - this.canvasContext.draw(); + this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height); + }, + handleClose() { + this.layerOpened = false; + this.cavShow = false; + setTimeout(() => { + this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height); + }, 100); }, handleWriteStart(evt) { - if (evt.type != 'touchstart') { - return false; + if (evt.type !== 'touchstart' || !this.canvasContext) { + return; } - this.canvasContext.setFillStyle('#1A1A1A'); + this.canvasContext.fillStyle = '#111111'; const point = { x: evt.touches[0].x, y: evt.touches[0].y, @@ -112,8 +148,8 @@ this._pointToLine(this.curLine); }, handleWriteMove(evt) { - if (evt.type != 'touchmove') { - return false; + if (evt.type !== 'touchmove') { + return; } if (evt.cancelable) { // 判断默认行为是否已经被禁用 @@ -137,8 +173,8 @@ this._pointToLine(this.curLine); }, handleWriteEnd(evt) { - if (evt.type != 'touchend') { - return 0; + if (evt.type !== 'touchend') { + return; } const point = { x: evt.changedTouches[0].x, @@ -167,14 +203,14 @@ if (point.x > this.cutArea.right) { this.cutArea.right = point.x; } - if (this.cavWidth - point.x <= 0) { - this.cutArea.right = this.cavWidth; + if (this.canvas.width - point.x <= 0) { + this.cutArea.right = this.canvas.width; } if (point.y > this.cutArea.bottom) { this.cutArea.bottom = point.y; } - if (this.cavHeight - point.y <= 0) { - this.cutArea.bottom = this.cavHeight; + if (this.canvas.height - point.y <= 0) { + this.cutArea.bottom = this.canvas.height; } if (point.x < this.cutArea.left) { this.cutArea.left = point.x; @@ -265,27 +301,28 @@ r2 = (line[1].r + line[0].r) / 2; } let n = 5; - let point = []; + let points = []; for (let i = 0; i < n; i++) { let t = i / (n - 1); let x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2; let y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2; let r = lastRadius + ((this.radius - lastRadius) / n) * i; - point.push({ x: x, y: y, r: r }); - if (point.length == 3) { - let a = this._ctaCalc( - point[0].x, - point[0].y, - point[0].r, - point[1].x, - point[1].y, - point[1].r, - point[2].x, - point[2].y, - point[2].r + points.push({ x: x, y: y, r: r }); + if (points.length == 3) { + this._bethelDraw( + this._ctaCalc( + points[0].x, + points[0].y, + points[0].r, + points[1].x, + points[1].y, + points[1].r, + points[2].x, + points[2].y, + points[2].r, + ), ); - this._bethelDraw(a, true); - point = [{ x: x, y: y, r: r }]; + points = [{ x: x, y: y, r: r }]; } } this.curLine = line; @@ -368,65 +405,91 @@ } return a; }, - _bethelDraw(point, isFill) { + _bethelDraw(points) { const ctx = this.canvasContext; ctx.beginPath(); - ctx.moveTo(point[0].mx, point[0].my); - for (let i = 1; i < point.length; i++) { + ctx.moveTo(points[0].mx, points[0].my); + for (let i = 1; i < points.length; i++) { ctx.bezierCurveTo( - point[i].c1x, - point[i].c1y, - point[i].c2x, - point[i].c2y, - point[i].ex, - point[i].ey + points[i].c1x, + points[i].c1y, + points[i].c2x, + points[i].c2y, + points[i].ex, + points[i].ey, ); } + ctx.closePath(); ctx.stroke(); - if (isFill !== undefined) { - // 后绘制的图形会覆盖前面的图形, 绘制时注意先后顺序 - ctx.fill(); - } - ctx.draw(true); + ctx.fill(); + }, + _brushingGround(callback) { + Taro.canvasToTempFilePath({ + canvas: this.canvas, + x: 0, + y: 0, + width: Math.ceil(this.canvas.width), + height: Math.ceil(this.canvas.height), + destWidth: Math.ceil(this.canvas.width), + destHeight: Math.ceil(this.canvas.height), + quality: 1, + fileType: 'png', + success: res => { + const ctx = this.canvasContext; + ctx.fillStyle = '#ffffff'; + ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + // 重新绘制 + const image = this.canvas.createImage(); + image.onload = () => { + const dpr = Taro.getSystemInfoSync().pixelRatio; + ctx.drawImage( + image, + 0, + 0, + this.canvas.width / dpr, + this.canvas.height / dpr, + ); + callback(); + }; + image.src = res.tempFilePath; + }, + }); }, handleSaveDraw() { if (this.firstTouch) { Tools.toast('请书写签名!'); + return; } - const delta = 20; - const clipArea = { x: 0, y: 0, w: 0, h: 0 }; - clipArea.x = Math.max(this.cutArea.left - delta, 0); - clipArea.y = Math.max(this.cutArea.top - delta, 0); - const realRight = Math.min(this.cutArea.right + delta, this.cavWidth); - const realBottom = Math.min(this.cutArea.bottom + delta, this.cavHeight); - clipArea.w = realRight - clipArea.x; - clipArea.h = realBottom - clipArea.y; - Taro.canvasToTempFilePath({ - canvasId: this.cavId, - x: clipArea.x, - y: clipArea.y, - width: clipArea.w, - height: clipArea.h, - destWidth: clipArea.w, - destHeight: clipArea.h, - quality: 0.6, - fileType: 'jpeg', - success: res => { - this._callback(res.tempFilePath); - this.layerOpened = false; - }, + this._brushingGround(() => { + const delta = 20; + const clipArea = { x: 0, y: 0, w: 0, h: 0 }; + clipArea.x = Math.max(this.cutArea.left - delta, 0); + clipArea.y = Math.max(this.cutArea.top - delta, 0); + const realRight = Math.min(this.cutArea.right + delta, this.canvas.width); + const realBottom = Math.min( + this.cutArea.bottom + delta, + this.canvas.height, + ); + clipArea.w = realRight - clipArea.x; + clipArea.h = realBottom - clipArea.y; + Taro.canvasToTempFilePath({ + canvas: this.canvas, + x: clipArea.x, + y: clipArea.y, + width: clipArea.w, + height: clipArea.h, + destWidth: clipArea.w, + destHeight: clipArea.h, + quality: 0.6, + fileType: 'jpeg', + success: res => { + this._callback(res.tempFilePath); + this.layerOpened = false; + }, + }); }); }, }, - mounted() { - this.$nextTick(() => { - this.canvasContext = Taro.createCanvasContext(this.cavId, this); - const $container = $(this.$refs.drawing).parent(); - setTimeout(() => { - $container.width().then(w => (this.cavWidth = w)); - $container.height().then(h => (this.cavHeight = h)); - }, 0); - }); - }, + mounted() {}, }; </script> \ No newline at end of file -- Gitblit v1.9.1