微信小程序电子签名实现

实现签名方法就是使用canvas

<canvas canvas-id="firstCanvas" id='firstCanvas' bindtouchstart="bindtouchstart" bindtouchmove="bindtouchmove"></canvas>

<!-- 旋装图片 -->
<canvas canvas-id="saveImg" id='saveImg'></canvas>

<view class="clear" hidden="{{!sureBtn}}" bindtap='clear'>重新签名</view>
<view class="save {{sureBtn?'sureBet':''}}" bindtap='export'>完成</view>

在canvas上绑定手指点击事件和移动事件:

mymoa-2fn99.gif

上图是想要实现的效果,
有几个考虑的点:

  • 1、签字区域和按钮都是横屏显示的,这个首先想到的使用微信小程序的方法直接在json文件设置"pageOrientation":"landscape",但效果是整个屏幕横屏,标题也横,效果不同。只能通过css方法旋转实现按钮横屏展示
  • 2、签字区域有个占位符,签字的时候需要去除,首先想到的是用个view去占位,然后点击切换为canvas,但是个人觉的略显刻意,就用canvas来旋转实现,bindtouchstart时让文字为空,这样也多了一个设置默认文字的函数
  • 3、生成图片,在使用wx.canvasToTempFilePath({})的时候发现生成的图片也是反着的,这里用了一个笨方法,添加一个canvas来单独处理图片旋转
//index.js
//获取应用实例
const app = getApp()

Page({
  data: {
    context: null,
    index: 0,
    height: 0,
    width: 0,
    writeTips: '请清晰书写您的英文签名',
    writeTipsTrue: true,
    src:'',
    sureBtn:false,
    saveContext:null
  },
  /**记录开始点 */
  bindtouchstart: function (e) {
    let { writeTipsTrue } = this.data
    if (writeTipsTrue) {

      this.data.context.clearRect(0, 0, this.data.width, this.data.height);
      this.setData({ writeTipsTrue: false, sureBtn:true })
    }
    this.data.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y)
  },
  /**记录移动点,刷新绘制 */
  bindtouchmove: function (e) {
    this.data.context.setLineWidth(2)       // 设置线条宽度
    this.data.context.lineTo(e.changedTouches[0].x, e.changedTouches[0].y);
    this.data.context.stroke();
    this.data.context.draw(true);
    this.data.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y);
  },

  /**清空画布 */
  clear () {
    let context = this.data.context
    this.setData({ writeTipsTrue: true, sureBtn:false })
    context.clearRect(0, 0, this.data.width, this.data.height);
    // this.data.saveContext.clearRect(0, 0, this.data.height, this.data.width);
    context.save();
    context.setTransform(1, 0, 0, 1, Math.ceil(this.data.width / 2), 155);        // 旋转画布 默认文字区域
    context.rotate(Math.PI / 2);
    let str = this.data.writeTips;
    context.setFontSize(24)
    context.setFillStyle('#ADADB2');
    context.fillText(str, 0, 0)
    context.restore();
    context.draw()
  },
  /**导出图片 */
  export () {
    const that = this;
    let signImg;
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: that.data.width,
      height: that.data.height,
      destWidth: that.data.width,
      destHeight: that.data.height,
      canvasId: 'firstCanvas',
      success (res) {
        console.log(res.tempFilePath)
        signImg = res.tempFilePath
        that.setData({ src1: signImg})
        //下载图片

        wx.getImageInfo({
          src: signImg, // 签字画布生成的暂存地址
          success (res) {
            // canvas绘制图片需要下载图片或者getImageInfo
            console.log(res,'res');

            let rototalImg = res.path
            that.setData({ src: rototalImg})
            if (rototalImg) {
              // 单独处理图片旋转
              that.saveImg(rototalImg)

            }
          }
        })
      }
    })
  },

  // drew img
  saveImg (signImg){
    if (!this.data.sureBtn){
      app.toast(this, {
        type: 'text',
        text: '请清晰书写您的英文签名'
      })
      return

    }
    // 旋转图
    let that = this
    const context = wx.createCanvasContext('saveImg');
    this.setData({saveContext:context})
    context.translate(that.data.width / 2, that.data.height / 2)
    context.setTransform(1, 0, 0, 1, 0, Math.ceil(that.data.height / 2) -20);
    context.rotate(-Math.PI / 2)
    // context.drawImage(signImg, -that.data.width / 2, -that.data.height / 2, that.data.width, that.data.height)
    context.drawImage(signImg, 0, 0, that.data.width, that.data.height)
   
    // context.fill()
    //绘制图片   生成图片函数写在draw()的回调中,不然会出现还没有画图就生成图片的问题
    context.draw(true,()=>{
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: that.data.height,
        height: that.data.width,
        destWidth: that.data.height,
        destHeight: that.data.width,
        canvasId: 'saveImg',
        fileType: 'png',
        success: function (res) {
          var tempFilePath = res.tempFilePath;
          console.log(tempFilePath);
          that.setData({ src: tempFilePath })
          // 生成图片 并返回上一页 赋值
          let curPages = getCurrentPages();
          var prevPage = curPages[curPages.length - 2]
          prevPage.setData({
            signImg: tempFilePath,
          })
          wx.navigateBack({
            delta: 1
          });
        },
        fail: function (res) {
          console.log(res);
        }
      });
    })
   
  },
  onLoad: function (options) {
    
  },
  onShow: function () {
    // 进入页面渲染canvas
    let query = wx.createSelectorQuery();
    const that = this;
    let context
    query.select('#firstCanvas').boundingClientRect();
    query.exec(function (rect) {
      let width = rect[0].width;
      let height = rect[0].height;
      that.setData({
        width,
        height
      });
      const context = wx.createCanvasContext('firstCanvas')
      that.setData({
        context: context
      })
      context.save();
      // context.translate(Math.ceil(width / 2) - 20,0)
      context.setTransform(1, 0, 0, 1, Math.ceil(width / 2), 155);
      context.rotate(Math.PI / 2);
      let str = that.data.writeTips;
      // context.fillText(str, Math.ceil((width - context.measureText(str).width) / 2), Math.ceil(height / 2) - 20)
      context.setFontSize(24)
      context.setFillStyle('#ADADB2');
      // context.fillRect(0, 0, that.data.height, that.data.width);
      context.fillText(str, 0, 0)
      context.restore();
      context.draw()
    });
  },
  // 弹窗
  onToast(){

    app.toast(this, {
      type: 'text',
      text: '生成成功'
    })
  },
  onShareAppMessage: (res) => { }
})

相关注释代码中都有,也么有优化,有好的方法,还希望大佬们多多指点

posted @ 2021-06-28 14:09  认认真真玩代码  阅读(3390)  评论(2编辑  收藏  举报
/* 看板娘 */