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