基于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>
相关推荐
计算机魔术师22 分钟前
OpenAI 发布 GPT-6 Astra:多项基准刷新纪录, cybersecurity 能力达 Critical 阈值
前端
xy345324 分钟前
Axure9.0中继器遮罩实现方法
前端·ui·html·axure·原型·产品设计
风骏时光牛马31 分钟前
智能任务自动化协同AI工作流
前端
IT_陈寒40 分钟前
Python的多线程居然是个假把式?搞清GIL让我少熬三天夜
前端·人工智能·后端
宿67441 分钟前
vue3-config
前端·javascript·vue.js
明月_清风42 分钟前
位图与布隆过滤器:海量数据下的"存在性判断"艺术
前端·后端·算法
明月_清风1 小时前
Hash 表从入门到精通:Go 实战与工程细节
前端·后端·算法
非凡ghost2 小时前
AI修图不“造假“,摄影师的出片效率加速器
服务器·前端·人工智能·电脑
2601_951615202 小时前
网页设计模板源码 web前端模板网页源码下载
前端
mmsx2 小时前
osmdroid 地图实战 03|地图的"分层世界":离线方案、图层模型与 Overlay 体系
android·前端