uniapp使用Canvas实现电子签名

来源:

公司的一个需求,需要给新注册的会员和客商需要增加签署协议功能;

之前的思路:
1、使用vue-signature-pad来实现电子签名,但是安卓手机不兼容;
2、uniapp插件市场来实现,但是对HBuilderX的版本有要求,无奈公司只能使用3.4.7版本;

前面2种思路都不行那就用Canvas来实现

Canvass

canvas 是 html 的一个标签,它可以结合 JavaScript 提供的 canvasApi 来绘制各种各样的图形。canvas 主要用于绘制 2D 图形。注意:当你不设置 canvas 的宽高时,它的默认宽高是 300px、150px。

需要实现的功能如图:
uniapp使用Canvas实现电子签名_第1张图片

代码实现

EctronicSignature.vue




EctronicSignature.ts

 curDrawArr: any = [];
  startX: any = 0;
  startY: any = 0;
  ctx: any = {};
  begin: Boolean = false;
  bgColor: String = 'white'; //背景色
  lineWidth: Number = 4; //画笔宽度
  penMode: Boolean = true; //打开画笔  开关
  currentTab: any = 1;
  currentIndex: any = 0;
  selectPointer: any = []; //所有选中的线
  cache: any = '';
  points: any = [];

  onReady() {
    this.ctx = uni.createCanvasContext('drawCanvas', this); // 获取canvas上下文对象 vue的写法是先获取,之后通过.getContext("2d")来获取上下文
    this.cache = new Map(); // 缓存
    this.ctx.setLineWidth(this.lineWidth); // 设置画笔的粗细
  }

  // ctx.draw()绘制结果呈现在canvas
  // isReverse: 是否保留之前的像素
  draw(isReverse = false, cb) {
    this.ctx.draw(isReverse, () => {
      if (cb && typeof cb == 'function') {
        cb();
      }
    });
  }

  // 绘画 开始
  touchStart(e) {
    console.log('绘画开始', e.touches[0].x, e.touches[0].y);
    // customPrint('我能够进行绘制');
    if (this.penMode) {
      this.lineBegin(e.touches[0].x, e.touches[0].y);
      this.lineAddPoint(e.touches[0].x, e.touches[0].y);
      this.draw(true, ''); // 呈现画面
    }
    this.points.push([e.touches[0].x, e.touches[0].y]); // 存储绘制的点
    this.selectPointer.push([[e.touches[0].x, e.touches[0].y]]);
  }

  // 开始绘制线条
  lineBegin(x, y) {
    this.begin = true; // 作为一个标记代表开始绘画
    this.ctx.beginPath(); // 开始创建一个路径
    this.startX = x;
    this.startY = y;
    this.ctx.moveTo(this.startX, this.startY); // 将路径移动到画布中的指定点
    this.lineAddPoint(x, y); // 绘制线条中间添加
  }

  // 绘画 移动
  touchMove(e) {
    console.log('绘画移动', e.touches[0].x, e.touches[0].y);

    if (this.begin) {
      if (this.penMode) {
        this.lineAddPoint(e.touches[0].x, e.touches[0].y);
        this.draw(true, '');
      }
      this.points.push([e.touches[0].x, e.touches[0].y]);
      this.selectPointer[this.selectPointer.length - 1].push([e.touches[0].x, e.touches[0].y]);
    }
  }

  // 绘制线条中间添加点
  lineAddPoint(x, y) {
    this.ctx.moveTo(this.startX, this.startY);
    this.ctx.lineTo(x, y); // 增加一个新的点,然后创建一条从上次指定点到目标点的线
    this.ctx.stroke(); // 画出当前路径的边框
    this.startX = x;
    this.startY = y;
  }

  // 绘画 结束
  touchEnd(e) {
    if (this.penMode) {
      // this.curDrawArr = [];
      this.points = [];
      this.lineEnd();
    }
  }

  // 绘制线条结束
  lineEnd() {
    this.ctx.closePath(); // 关闭一个路径,关闭路径会连接起点和终点
    this.begin = false;
  }

  // 检验画布是否为空
  isCanvasBlank(canvas) {
    const blank = document.createElement('canvas'); //系统获取一个空canvas对象
    blank.width = canvas.width;
    blank.height = canvas.height;
    return canvas.toDataURL() == blank.toDataURL();  // .toDataURL()将canvas对象转换为base64位编码
  }

  // 保存 图片数据
  saveImage() {
    const _this = this;
    uni.canvasToTempFilePath({
      canvasId: 'drawCanvas',
      success: function(res) {
        console.log('res ==>', res);
        // 在H5平台下,tempFilePath 为 base64
        // this.uploadimage(res.tempFilePath,"save",page.currentTab)
        const canvas = document.getElementsByTagName('canvas')[0];
        if (_this.isCanvasBlank(canvas)) {
          uni.showToast({
            title: '请签字!!!',
            icon: 'none',
          });
          return false;
        }
      },
    });
  }

   //清除
  clearDrawBoard() {
    this.ctx.draw();
    this.selectPointer = [];
  }
  }

推荐资料

https://www.runoob.com/html/html5-canvas.html
https://uniapp.dcloud.net.cn/component/canvas.html#canvas
https://open.dingtalk.com/document/personalapp/setlinewidth

你可能感兴趣的:(工作积累,uni-app,前端)