基于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>
相关推荐
A_aspectJ2 小时前
【Bootstrap V4系列】学习入门教程之 组件-输入组(Input group)
前端·css·学习·bootstrap·html
兆。2 小时前
电子商城后台管理平台-Flask Vue项目开发
前端·vue.js·后端·python·flask
互联网搬砖老肖2 小时前
Web 架构之负载均衡全解析
前端·架构·负载均衡
sunbyte3 小时前
Tailwind CSS v4 主题化实践入门(自定义 Theme + 主题模式切换)✨
前端·javascript·css·tailwindcss
湛海不过深蓝4 小时前
【css】css统一设置变量
前端·css
程序员的世界你不懂5 小时前
tomcat6性能优化
前端·性能优化·firefox
爱吃巧克力的程序媛5 小时前
QML ProgressBar控件详解
前端
进取星辰5 小时前
21、魔法传送阵——React 19 文件上传优化
前端·react.js·前端框架
wqqqianqian5 小时前
国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开Word文件,并用前端对话框实现填空填表
linux·前端·word·pageoffice
BillKu5 小时前
CSS实现图片垂直居中方法
前端·javascript·css