当前位置:首页 > VUE

vue实现手写签名

2026-01-16 08:39:47VUE

Vue 实现手写签名功能

使用 canvas 实现基础签名

在 Vue 项目中创建一个签名组件,使用 HTML5 的 canvas 元素作为画布。通过监听鼠标或触摸事件来捕获用户的绘制动作。

<template>
  <div>
    <canvas 
      ref="canvas"
      @mousedown="startDrawing"
      @mousemove="draw"
      @mouseup="stopDrawing"
      @mouseleave="stopDrawing"
      @touchstart="startDrawing"
      @touchmove="draw"
      @touchend="stopDrawing"
    ></canvas>
    <button @click="clearCanvas">清除</button>
    <button @click="saveSignature">保存</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isDrawing: false,
      lastX: 0,
      lastY: 0,
    };
  },
  mounted() {
    this.setupCanvas();
  },
  methods: {
    setupCanvas() {
      const canvas = this.$refs.canvas;
      canvas.width = canvas.offsetWidth;
      canvas.height = canvas.offsetHeight;
      this.ctx = canvas.getContext('2d');
      this.ctx.strokeStyle = '#000';
      this.ctx.lineWidth = 2;
      this.ctx.lineCap = 'round';
    },
    startDrawing(e) {
      this.isDrawing = true;
      const pos = this.getPosition(e);
      this.lastX = pos.x;
      this.lastY = pos.y;
    },
    draw(e) {
      if (!this.isDrawing) return;
      const pos = this.getPosition(e);
      this.ctx.beginPath();
      this.ctx.moveTo(this.lastX, this.lastY);
      this.ctx.lineTo(pos.x, pos.y);
      this.ctx.stroke();
      this.lastX = pos.x;
      this.lastY = pos.y;
    },
    stopDrawing() {
      this.isDrawing = false;
    },
    getPosition(e) {
      const canvas = this.$refs.canvas;
      const rect = canvas.getBoundingClientRect();
      return {
        x: (e.clientX || e.touches[0].clientX) - rect.left,
        y: (e.clientY || e.touches[0].clientY) - rect.top
      };
    },
    clearCanvas() {
      const canvas = this.$refs.canvas;
      this.ctx.clearRect(0, 0, canvas.width, canvas.height);
    },
    saveSignature() {
      const dataURL = this.$refs.canvas.toDataURL('image/png');
      this.$emit('save', dataURL);
    }
  }
};
</script>

响应式设计优化

确保签名区域在不同设备上都能正常使用,特别是移动设备上的触摸支持。

<style scoped>
canvas {
  border: 1px solid #000;
  width: 100%;
  height: 300px;
  background-color: #fff;
  touch-action: none;
}
button {
  margin-top: 10px;
  padding: 8px 16px;
}
</style>

使用第三方库简化实现

对于更复杂的签名需求,可以考虑使用专门的签名库如 vue-signaturesignature_pad

vue实现手写签名

安装 signature_pad:

npm install signature_pad

在 Vue 中使用:

vue实现手写签名

<template>
  <div>
    <canvas ref="canvas"></canvas>
    <button @click="clear">清除</button>
    <button @click="save">保存</button>
  </div>
</template>

<script>
import SignaturePad from 'signature_pad';

export default {
  mounted() {
    this.signaturePad = new SignaturePad(this.$refs.canvas, {
      backgroundColor: 'rgba(255, 255, 255, 0)',
      penColor: 'rgb(0, 0, 0)'
    });
    this.resizeCanvas();
    window.addEventListener('resize', this.resizeCanvas);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resizeCanvas);
  },
  methods: {
    resizeCanvas() {
      const canvas = this.$refs.canvas;
      const ratio = Math.max(window.devicePixelRatio || 1, 1);
      canvas.width = canvas.offsetWidth * ratio;
      canvas.height = canvas.offsetHeight * ratio;
      canvas.getContext('2d').scale(ratio, ratio);
      this.signaturePad.clear();
    },
    clear() {
      this.signaturePad.clear();
    },
    save() {
      if (this.signaturePad.isEmpty()) {
        alert('请先签名');
        return;
      }
      const dataURL = this.signaturePad.toDataURL();
      this.$emit('save', dataURL);
    }
  }
};
</script>

保存签名数据

将签名数据转换为 base64 格式的图片数据,可以方便地提交到服务器或本地存储。

// 在父组件中接收签名数据
<signature-pad @save="handleSave" />

methods: {
  handleSave(dataURL) {
    // 提交到服务器或本地处理
    console.log(dataURL);
    // 或者转换为Blob对象
    fetch(dataURL)
      .then(res => res.blob())
      .then(blob => {
        const file = new File([blob], 'signature.png', { type: 'image/png' });
        // 处理文件
      });
  }
}

移动端优化注意事项

确保在移动设备上有良好的触摸体验,需要注意以下几点:

  • 禁用页面滚动防止签名时页面移动
  • 处理触摸事件的多点触控问题
  • 考虑不同设备的像素密度问题
  • 增加签名区域的视觉反馈
// 防止触摸时页面滚动
document.addEventListener('touchmove', function(e) {
  if (isDrawing) {
    e.preventDefault();
  }
}, { passive: false });

通过以上方法,可以在 Vue 项目中实现一个功能完善的手写签名组件,支持桌面和移动设备,并能够保存签名结果。

标签: vue
分享给朋友:

相关文章

vue实现密码

vue实现密码

Vue 密码输入组件实现 基础密码输入框实现 使用 Vue 的 v-model 指令绑定数据,并通过 type="password" 设置输入类型为密码: <template> &…

vue点击实现排序

vue点击实现排序

实现点击排序的方法 在Vue中实现点击排序功能,可以通过以下几种方式完成: 使用计算属性结合排序方法 定义一个响应式数据存储排序状态,通过计算属性动态返回排序后的数组。点击事件切换排序状态。…

前端多线程实现vue

前端多线程实现vue

前端多线程与Vue的结合 在Vue中实现多线程通常通过Web Worker技术完成。Web Worker允许在后台线程中运行脚本,避免阻塞主线程,适合处理计算密集型任务。 使用Web Worker的…

vue实现页面截屏

vue实现页面截屏

使用html2canvas库实现截屏 html2canvas是一个流行的JavaScript库,可以将DOM元素转换为Canvas图像。在Vue项目中安装html2canvas: npm insta…

vue实现防抖节流

vue实现防抖节流

Vue 中实现防抖(Debounce) 防抖的核心是延迟执行函数,在连续触发时取消前一次的调用,只执行最后一次。适用于输入框搜索、窗口大小调整等场景。 方法1:使用 Lodash 的 _.debou…

vue实现画圆弧并着色

vue实现画圆弧并着色

在 Vue 中实现画圆弧并着色 使用 Canvas API 绘制圆弧 在 Vue 组件的 mounted 钩子中,通过 Canvas API 绘制圆弧。创建一个 canvas 元素并获取其上下文:…