当前位置:首页 > VUE

vue 移动端实现签名

2026-02-09 15:20:05VUE

移动端签名功能实现(Vue)

核心思路:通过Canvas绘图实现签名,适配移动端触摸事件,支持导出图片。

vue 移动端实现签名

依赖安装

使用vue-signature-pad库简化开发:

vue 移动端实现签名

npm install vue-signature-pad

或原生Canvas实现(无需依赖):

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

核心实现代码

export default {
  data() {
    return {
      isDrawing: false,
      canvas: null,
      ctx: null
    }
  },
  mounted() {
    this.initCanvas()
  },
  methods: {
    initCanvas() {
      this.canvas = this.$refs.canvas
      this.ctx = this.canvas.getContext('2d')

      // 适配高清屏
      const ratio = window.devicePixelRatio || 1
      this.canvas.width = this.canvas.offsetWidth * ratio
      this.canvas.height = this.canvas.offsetHeight * ratio
      this.ctx.scale(ratio, ratio)

      // 设置绘制样式
      this.ctx.strokeStyle = '#000'
      this.ctx.lineWidth = 2
      this.ctx.lineCap = 'round'
    },

    startDrawing(e) {
      this.isDrawing = true
      const pos = this.getPosition(e)
      this.ctx.beginPath()
      this.ctx.moveTo(pos.x, pos.y)
    },

    draw(e) {
      if (!this.isDrawing) return
      const pos = this.getPosition(e)
      this.ctx.lineTo(pos.x, pos.y)
      this.ctx.stroke()
    },

    stopDrawing() {
      this.isDrawing = false
    },

    getPosition(e) {
      const rect = this.canvas.getBoundingClientRect()
      return {
        x: (e.touches ? e.touches[0].clientX : e.clientX) - rect.left,
        y: (e.touches ? e.touches[0].clientY : e.clientY) - rect.top
      }
    },

    clearCanvas() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
    },

    saveSignature() {
      const image = this.canvas.toDataURL('image/png')
      // 可通过API上传或本地保存
      console.log(image)
    }
  }
}

样式优化

.signature-container {
  position: relative;
  width: 100%;
  height: 300px;
}

canvas {
  width: 100%;
  height: 100%;
  border: 1px solid #ddd;
  background-color: #f9f9f9;
  touch-action: none; /* 防止触摸滚动 */
}

button {
  margin-top: 10px;
  padding: 8px 15px;
}

移动端适配要点

  1. 防抖动处理:添加touch-action: none防止页面滚动干扰
  2. 高清屏适配:通过devicePixelRatio调整Canvas分辨率
  3. 双端事件:同时监听touchmouse事件
  4. 性能优化:复杂签名可考虑使用requestAnimationFrame

进阶功能

  1. 压力感应:通过touch.force(iOS)或event.pressure(Android)实现笔迹粗细变化
  2. 撤销功能:使用数组记录绘制路径实现多步撤销
  3. 背景图签名:在Canvas底层叠加背景图片
  4. 本地存储:使用localStorage缓存签名数据

注意事项

  1. 部分安卓机型需要添加meta标签禁用缩放:
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  2. 横竖屏切换时需要重新计算Canvas尺寸
  3. 签名图片上传建议转为Blob格式减少传输体积

标签: vue
分享给朋友:

相关文章

vue插槽实现

vue插槽实现

插槽的基本概念 Vue插槽(Slot)是一种内容分发机制,允许父组件向子组件传递模板片段,子组件通过<slot>标签定义接收位置。插槽的核心作用是增强组件的灵活性和复用性。 默认插槽 子…

vue实现画图

vue实现画图

Vue 实现画图功能 在 Vue 中实现画图功能通常需要结合 HTML5 的 <canvas> 元素或第三方库。以下是几种常见的方法: 使用原生 Canvas API 通过 Vue 直接…

vue实现表白

vue实现表白

Vue 实现表白页面 使用 Vue 可以快速创建一个动态、交互式的表白页面。以下是一个简单的实现方案: 基础结构 创建一个 Vue 项目或单文件组件,包含以下核心部分: <template&…

vue实现博客

vue实现博客

Vue 实现博客的基本步骤 使用 Vue.js 实现一个博客系统可以分为前端和后端两部分。以下是基于 Vue 的前端实现方案,后端可以选择 Node.js、Django 或其他框架。 项目初始化 使…

vue实现抽奖

vue实现抽奖

Vue 实现抽奖功能 基本抽奖逻辑 创建一个Vue组件,包含奖品列表、抽奖按钮和结果显示区域。使用随机数生成器选择奖品。 <template> <div> <…

vue 实现评分

vue 实现评分

Vue 实现评分功能 在 Vue 中实现评分功能可以通过多种方式完成,包括使用第三方组件库或自定义实现。以下是两种常见的方法: 使用第三方组件库(如 Element UI) Element UI 提…