当前位置:首页 > 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 中实现静态查询通常指不依赖后端接口,直接在前端处理数据筛选或搜索功能。以下是几种常见实现方式: 使用计算属性过滤数据 通过计算属性对静态数据进行筛选,适合简单查询场…

vue实现发送值接受值

vue实现发送值接受值

Vue 实现父子组件传值 父组件向子组件传值(props) 父组件通过 v-bind 或简写 : 向子组件传递数据。子组件通过 props 接收数据。 父组件代码: <template&g…

vue 实现列表

vue 实现列表

Vue 实现列表的方法 在 Vue 中实现列表通常使用 v-for 指令,结合数组或对象数据渲染动态列表。以下是几种常见的实现方式: 基础列表渲染 使用 v-for 指令遍历数组,渲染列表项。ite…

vue alert实现

vue alert实现

使用 Vue 实现 Alert 组件 在 Vue 中实现 Alert 组件可以通过自定义组件或结合第三方库完成。以下是几种常见方法: 自定义 Alert 组件 创建一个可复用的 Alert 组件,通…

vue实现ppt

vue实现ppt

Vue 实现 PPT 的功能 Vue 可以结合第三方库或自定义组件实现类似 PPT 的演示效果。以下是几种常见的方法: 使用第三方库 reveal.js reveal.js 是一个流行的演示框架,支…

vue实现mui

vue实现mui

使用 Vue 实现 MUI(Material-UI)风格的界面 Vue 本身不直接提供 MUI(Material Design)组件,但可以通过集成第三方库或手动实现来达到类似效果。以下是几种常见方法…