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>
相关推荐
品克缤26 分钟前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小沐°41 分钟前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
Irene19911 小时前
Vue3 <Suspense> 使用指南与注意事项
vue.js·suspense
qq_419854051 小时前
CSS动效
前端·javascript·css
南村群童欺我老无力.2 小时前
Flutter应用鸿蒙迁移实战:性能优化与渐进式迁移指南
javascript·flutter·ci/cd·华为·性能优化·typescript·harmonyos
花哥码天下2 小时前
恢复网站console.log的脚本
前端·javascript·vue.js
北辰alk2 小时前
Vue 的 nextTick:破解异步更新的玄机
vue.js
北辰alk2 小时前
Vue 技巧揭秘:一个事件触发多个方法,你竟然还不知道?
vue.js
北辰alk3 小时前
Vue 中 computed 和 watch 的深度解析:别再用错了!
vue.js
奔跑的呱呱牛3 小时前
geojson-to-wkt 坐标格式转换
javascript·arcgis