h5 签名 vue

需求:在点击签名弹窗签名,点确定回显

1、封装一个.vue 文件,我是封装一个Signature.vue文件,放在components目录下

Signature.vue全部内容

javascript 复制代码
<template>
  <div class="signature">
    <canvas class="signature-canvas" ref="canvas" @touchstart="startDrawing" @touchmove="draw" @touchend="stopDrawing"></canvas>
  </div>
</template>

<script>
export default {
  name: 'Signature',
  data() {
    return {
      isDrawing: false,
      signatureData: [],
    };
  },
  methods: {
    startDrawing(event) {
      const canvas = this.$refs.canvas;
      const rect = canvas.getBoundingClientRect();
      const scaleX = canvas.width / rect.width;
      const scaleY = canvas.height / rect.height;
      const x = (event.touches[0].clientX - rect.left) * scaleX;
      const y = (event.touches[0].clientY - rect.top) * scaleY;

      const ctx = canvas.getContext('2d');
      ctx.beginPath();
      ctx.moveTo(x, y);

      this.isDrawing = true;
      this.signatureData.push({ x: x / canvas.width, y: y / canvas.height });
    },
    draw(event) {
      if (this.isDrawing) {
        const canvas = this.$refs.canvas;
        const rect = canvas.getBoundingClientRect();
        const scaleX = canvas.width / rect.width;
        const scaleY = canvas.height / rect.height;
        const x = (event.touches[0].clientX - rect.left) * scaleX;
        const y = (event.touches[0].clientY - rect.top) * scaleY;

        const ctx = canvas.getContext('2d');
        ctx.lineTo(x, y);
        ctx.stroke();

        this.signatureData.push({ x: x / canvas.width, y: y / canvas.height });
      }
    },

    stopDrawing() {
      this.isDrawing = false;
    },

    clear() {
      this.signatureData = [];

      const canvas = this.$refs.canvas;
      this.ctx = canvas.getContext('2d');
      this.ctx.clearRect(0, 0, canvas.width, canvas.height);
    },
  },
};
</script>

<style lang="less" scoped>
.signature {
  position: relative;
}

.signature-canvas {
  display: block;
  border: 1px solid black;
  margin: 10px;
  width: calc(100% - 20px);
  height: 200px;
}
</style>

在list.vue 文件引入使用 上述文件 components/Signature.vue,获取到的this.model.signList 就是签名

由很多坐标组成

javascript 复制代码
<template>
<div class="van-doc-block">
      <h2 class="van-doc-block-title">第二位维保人员签名确认<span>*</span></h2>
      <van-cell-group inset>
        <div class="signature-wrap" @click="openSignatureHandle('two')">
          <div class="write-inner-wrap">
            <div v-show="model.signList && model.signList.length" class="img-wrap">
              <canvas class="signature-canvas" ref="outputCanvas"></canvas>
            </div>
            <div v-show="!model.signList || model.signList.length === 0" class="no-sign-wrap">点击此处进入签名区域</div>
          </div>
        </div>
      </van-cell-group>
    <van-popup v-model="signatureVisible" closeable position="bottom" :style="{ height: '45%' }">
      <div class="signature-popup-wrap">
        <Signature ref="signature"></Signature>
        <div class="button-wrap">
          <van-button type="default" native-type="button" @click="signatureClearHandle">清除</van-button>
          <van-button type="primary" native-type="button" @click.stop="signatureOkHandle">确定</van-button>
        </div>
      </div>
    </van-popup>
    </div>
    </template>
    <script>
import Signature from '@/components/Signature'; // 引入上述文件
export default {
  components: { Signature },
  data() {
    return {
    signatureVisible: false,
      },
      methods: {
       signatureClearHandle() {
      this.$refs['signature'].clear();
    },
	signatureOkHandle() {
       const signatureData = lo.cloneDeep(this.$refs['signature'].signatureData);
        this.$set(this.model, 'signList', signatureData);
        this.drawSavedSignature(signatureData, 'outputCanvas');
      
    },
    drawSavedSignature(signatureData, canvasOut) {
      this.$nextTick(() => {
        const canvas = this.$refs[canvasOut];

        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        if (signatureData && signatureData.length) {
          ctx.beginPath();
          ctx.moveTo(signatureData[0].x * canvas.width, signatureData[0].y * canvas.height);

          for (let i = 1; i < signatureData.length; i++) {
            const currentPoint = signatureData[i];
            const previousPoint = signatureData[i - 1];

            // 检查当前点和前一个点之间的距离,如果距离过大,则认为是新的笔画
            const distance = Math.sqrt(Math.pow(currentPoint.x - previousPoint.x, 2) + Math.pow(currentPoint.y - previousPoint.y, 2));
            if (distance > 0.1) {
              ctx.moveTo(currentPoint.x * canvas.width, currentPoint.y * canvas.height);
            } else {
              ctx.lineTo(currentPoint.x * canvas.width, currentPoint.y * canvas.height);
            }
          }

          ctx.stroke();
        }

        this.signatureVisible = false;
      });
    },
    openSignatureHandle(type) {
      this.showSignType = type;
      this.$nextTick(() => {
        const $signatureRef = this.$refs['signature'];
        if ($signatureRef) {
          this.$refs['signature'].clear();
        }
      });

      this.signatureVisible = true;
    },
    }
    }
  }
   </script>
相关推荐
没事多睡觉66643 分钟前
JavaScript 中 this 指向教程
开发语言·前端·javascript
asdfg12589631 小时前
replace(/,/g, ‘‘);/\B(?=(\d{3})+(?!\d))/;千分位分隔
开发语言·前端·javascript
W***D4551 小时前
nodejs链接redis
javascript·redis·bootstrap
梦6501 小时前
VUE树形表格组件如何自定义展开箭头以及箭头位置
javascript·vue.js·elementui
国服第二切图仔1 小时前
Electron for 鸿蒙PC项目开发之模态框组件
javascript·electron·harmonyos
_Jyann_1 小时前
uniapp两种方式实现自定义tabbar
前端·javascript·uni-app
一 乐1 小时前
数码商城系统|电子|基于SprinBoot+vue的数码商城系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·springboot
fruge1 小时前
React Server Components 实战:下一代 SSR 开发指南
前端·javascript·react.js
hxmmm1 小时前
preconnect、dns-prefetch、prerender、preload、prefetch
javascript