基于uniapp 实现画板签字

直接上效果图

代码

javascript 复制代码
<template>
  <view class="container">
    <!-- 签名画布 -->
    <view class="canvas-container">
      <canvas 
        canvas-id="signCanvas" 
        class="sign-canvas"
        @touchstart="handleTouchStart"
        @touchmove="handleTouchMove"
        @touchend="handleTouchEnd"
      ></canvas>
    </view>
    
    <!-- 操作按钮 -->
    <view class="button-group">
      <button @click="clearCanvas" class="btn">清除</button>
      <button @click="saveSignature" class="btn">保存签名</button>
    </view>
    
    <!-- 保存的签名预览 -->
    <view class="preview" v-if="imagePath">
      <image :src="imagePath" mode="widthFix"></image>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      ctx: null, // canvas 上下文
      points: [], // 存储绘制点
      isDrawing: false, // 是否正在绘制
      imagePath: '' // 保存的签名图片路径
    }
  },
  onReady() {
    // 初始化canvas上下文
    this.ctx = uni.createCanvasContext('signCanvas', this);
    
    // 设置画笔样式
    this.ctx.setStrokeStyle('#000000');
    this.ctx.setLineWidth(4);
    this.ctx.setLineCap('round');
    this.ctx.setLineJoin('round');
  },
  methods: {
    // 触摸开始
    handleTouchStart(e) {
      this.isDrawing = true;
      const startX = e.touches[0].x;
      const startY = e.touches[0].y;
      
      this.points = [{x: startX, y: startY}];
      
      // 开始新路径
      this.ctx.beginPath();
      this.ctx.moveTo(startX, startY);
    },
    
    // 触摸移动
    handleTouchMove(e) {
      if (!this.isDrawing) return;
      
      const moveX = e.touches[0].x;
      const moveY = e.touches[0].y;
      
      this.points.push({x: moveX, y: moveY});
      
      // 只保留最近的两个点用于绘制线段
      if (this.points.length > 2) {
        const lastTwoPoints = this.points.slice(-2);
        this.ctx.moveTo(lastTwoPoints[0].x, lastTwoPoints[0].y);
        this.ctx.lineTo(lastTwoPoints[1].x, lastTwoPoints[1].y);
        this.ctx.stroke();
        this.ctx.draw(true);
      }
    },
    
    // 触摸结束
    handleTouchEnd() {
      if (this.points.length < 2) {
        // 如果只有一个点,画一个点
        const point = this.points[0];
        this.ctx.arc(point.x, point.y, 2, 0, 2 * Math.PI);
        this.ctx.fill();
        this.ctx.draw(true);
      }
      
      this.isDrawing = false;
      this.points = [];
    },
    
    // 清除画布
    clearCanvas() {
      this.ctx.clearRect(0, 0, 10000, 10000);
      this.ctx.draw(true);
      this.imagePath = '';
    },
    
    // 保存签名
    saveSignature() {
      uni.canvasToTempFilePath({
        canvasId: 'signCanvas',
        success: (res) => {
          this.imagePath = res.tempFilePath;
          uni.showToast({
            title: '签名保存成功',
            icon: 'success'
          });
          
          // 这里可以添加将签名上传服务器的代码
          // this.uploadSignature(res.tempFilePath);
        },
        fail: (err) => {
          console.error('保存签名失败:', err);
          uni.showToast({
            title: '保存签名失败',
            icon: 'none'
          });
        }
      }, this);
    },
    
    // 上传签名到服务器(可选)
    uploadSignature(tempFilePath) {
      uni.uploadFile({
        url: '你的上传接口地址',
        filePath: tempFilePath,
        name: 'signature',
        success: (uploadRes) => {
          console.log('上传成功', uploadRes);
        },
        fail: (uploadErr) => {
          console.error('上传失败', uploadErr);
        }
      });
    }
  }
}
</script>

<style lang="scss" scoped>
.sign-canvas{
	width: 100vw;
	height: 70vh;
}
</style>
相关推荐
懋学的前端攻城狮7 分钟前
Next.js + TypeScript + Shadcn UI:构建高性能懒加载与无限滚动系统
前端·react.js·前端框架
宋辰月32 分钟前
Vue2的进阶Vue3
前端·javascript·vue.js
酷飞飞1 小时前
C语言的复合类型、内存管理、综合案例
java·c语言·前端
姜太小白2 小时前
【前端】CSS Grid布局介绍及示例
前端·css
风继续吹..6 小时前
后台管理系统权限管理:前端实现详解
前端·vue
yuanmenglxb20046 小时前
前端工程化包管理器:从npm基础到nvm多版本管理实战
前端·前端工程化
新手小新6 小时前
C++游戏开发(2)
开发语言·前端·c++
我不吃饼干7 小时前
【TypeScript】三分钟让 Trae、Cursor 用上你自己的 MCP
前端·typescript·trae
小杨同学yx8 小时前
前端三剑客之Css---day3
前端·css
Mintopia10 小时前
🧱 用三维点亮前端宇宙:构建你自己的 Three.js 组件库
前端·javascript·three.js