3

小程序实现手写签名

 2 years ago
source link: https://segmentfault.com/a/1190000041421576
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在微信小程序上实现手写签名,获取canvascontext新版本和旧版本有点坑,新版本在获取canvas后如果页面有滑动,则签名坐标出现异常(在微信开发者工具上会出现2022-2-17),但是在真机上即使滑动也不会出现异常,为了防止出现问题,暂时使用旧版本获取canvascontext

1.效果图

image.pngimage.png

2.相关代码

  • 1.canvas代码

    • 新版2d canvas
    <canvas
      id="canvas"
      class="canvas"
      canvas-id="canvas"
      type="2d"
      :disable-scroll="true"
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd"
      @touchcancel="handleTouchCancel"
    ></canvas>
    • 旧版canvas
    <canvas
      class="canvas"
      canvas-id="canvas"
      :disable-scroll="true"
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd"
      @touchcancel="handleTouchCancel"
    ></canvas>
  • 2.js相关

    • 获取新版2d canvas对象
    const query = uni.createSelectorQuery().in(this);
    query.select('.canvas').node(res => {
      const {
          _width,
          _height
      } = res.node;
      
      /* 获取canvas wxml节点 */
      this.canvas = res.node;
      this.canvasWidth = _width;
      this.canvasHeight = _height;
      /* 获取canvas 2dcontext */
      this.canvasContext= this.canvas.getContext('2d');
      
      /* 缩放设置canvas画布大小,防止笔迹错位 */
      const ratio = wx.getSystemInfoSync().pixelRatio;
      this.canvas.width = this.canvasWidth * ratio;
      this.canvas.height = this.canvasHeight * ratio;
      this.canvasContext.scale(ratio, ratio);
      
      /* 设置线条颜色 */
      this.canvasContext.strokeStyle = '#2A2A2A';
      /* 设置线条粗细 */
      this.canvasContext.lineWidth = 4;
      /* 设置线条的结束端点样式 */
      this.canvasContext.lineCap = 'round';
    }).exec()
    • 缩放设置canvas画布大小,防止笔迹错位,这点和页面滑动没有关系,不设置也会导致坐标错位
    const ratio = wx.getSystemInfoSync().pixelRatio;
    this.canvas.width = this.canvasWidth * ratio;
    this.canvas.height = this.canvasHeight * ratio;
    this.canvasContext.scale(ratio, ratio);
  • 旧版本获取canvas

    this.canvasContext = uni.createCanvasContext('canvas', this);
    /* 设置线条颜色 */
    this.canvasContext.setStrokeStyle('#2A2A2A');
    /* 设置线条粗细 */
    this.canvasContext.setLineWidth(4);
    /* 设置线条的结束端点样式 */
    this.canvasContext.setLineCap('round');
  • 签名js方法,新版本和旧版本只有一个draw的区别,新版本不需要使用draw方法

    /* 触摸开始 */
    handleTouchStart(e) {
      this.drawStartX = e.changedTouches[0].x;
      this.drawStartY = e.changedTouches[0].y;
        this.canvasContext.beginPath();
    },
    /* 触摸移动 */
    handleTouchMove(e) {
        /* 记录当前位置 */
        const tempX = e.changedTouches[0].x;
        const tempY = e.changedTouches[0].y;
    
        /* 画线 */
        this.canvasContext.moveTo(this.drawStartX, this.drawStartY);
        this.canvasContext.lineTo(tempX, tempY);
        this.canvasContext.stroke();
    
        /* 旧版draw方法,新版本不需要draw */
        this.canvasContext.draw(true);
    
        /* 重新记录起始位置 */
        this.drawStartX = tempX;
        this.drawStartY = tempY;
    },
    /* 触摸结束 */
    handleTouchEnd(e) {
        this.canvasContext.save();
    },
    /* 触摸取消 */
    handleTouchCancel(e) {
        this.canvasContext.save();
    },
    /* 清空画布 */
    clearCanvas() {
        this.canvasContext.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    },
  • canvas生成本地图片(我这里封装了组件,需要传入this防止this指向异常)

    /* 生成签名图片 */
    generateSignImage() {
        return new Promise((resolve, reject) => {
            uni.canvasToTempFilePath({
              x: 0,
              y: 0,
              // canvas: this.canvas, // 新版
              canvasId: 'canvas', // 旧版使用id
              width: this.canvasWidth,
              height: this.canvasHeight,
              destWidth: this.canvasWidth,
              destHeight: this.canvasHeight,
              fileType: 'png',
              quality: 1,
              success: res => {
                  resolve(res.tempFilePath)
              },
              fail: err => {
                  reject(err);
              }
            }, this)
        })
    },

    新版本的canvas主要是canvas wxml节点和canvas context中做了区分,旧版则只有一个canvas context就可以做全部的操作,在生成图片时,新版本是传入wxml对象,旧版本则是传入唯一canvasId,新版本canvas取消了draw方法

正在努力学习中,若对你的学习有帮助,留下你的印记呗(点个赞咯^_^)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK