微信小程序canvas实现个人签名,并保存为图片

使用微信小程序的canvas做了个人签名的功能,支持导出为图片和清空的功能。为了提供用户体验,在性能优化上做了很大提升。最后的保存图片是先保存为本地临时文件,然后上传服务器,从服务器请求预览。下面先上图,再公布代码

微信小程序canvas实现个人签名,并保存为图片

wxml代码为

<!--index.wxml-->
<view class="container">
  <canvas canvas-id="firstCanvas" id='firstCanvas' bindtouchstart="bindtouchstart" bindtouchmove="bindtouchmove"></canvas>
  <view class="btn">

    <button type="warn" bindtap='clear'>
      清除
    </button>
    <button type="primary"  bindtap='export'>
      提交
    </button>
  </view>

</view>

js代码为

//index.js
//获取应用实例
const app = getApp()

Page({
  data: {
    context: null,
    index: 0,
    height: 0,
    width: 0
  },
  /**记录开始点 */
  bindtouchstart: function(e) {
    this.data.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y)
  },
  /**记录移动点,刷新绘制 */
  bindtouchmove: function(e) {
   
    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: function() {
    this.data.context.clearRect(0, 0, this.data.width, this.data.height);
    this.data.context.draw();
    this.data.context.setStrokeStyle('#00ff00')
    this.data.context.setLineWidth(2)
    this.data.context.setFontSize(20)
    let str = "签名区域";
    this.data.context.fillText(str, Math.ceil((this.data.width - this.data.context.measureText(str).width) / 2), Math.ceil(this.data.height / 2) - 20)
    this.data.context.draw()
  },
  /**导出图片 */
  export: function() {
    const that=this;
    this.data.context.draw(false, wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: that.data.width,
      height: that.data.height,
      destWidth: that.data.width,
      destHeight: that.data.height,
      fileType: 'jpg',
      canvasId: 'firstCanvas',
      success(res) {
        wx.uploadFile({
          url: 'http://192.168.0.157:8089/uppic', 
          filePath: res.tempFilePath,
          name: 'file',
          success(res) {
            var url = "http://192.168.0.157:8089/pic?name=" + res.data
            wx.previewImage({
              // current: url, // 当前显示图片的http链接
              urls: [url], // 需要预览的图片http链接列表
              fail(f) {
                console.log(2)
                console.error(f)
              },
              success(s) {
                console.log(1)
                console.log(s)
              }
            })
          },
          fail(err) {
            wx.showToast({
              title: '上传失败',
              icon: 'none',
              duration: 2000
            })
          }
        })

      },
      fail() {
        wx.showToast({
          title: '导出失败',
          icon: 'none',
          duration: 2000
        })
      }
    }))

  },
  onLoad: function(options) {
    console.log(options.id);
    if (options.id) {
      wx.showToast({
        title: '姓名' + options.id,
        icon: 'success',
        duration: 2000
      })
    }
  },
  onShow: function() {
    let query = wx.createSelectorQuery();
    const that = this;
    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.setStrokeStyle('#00ff00')
      context.setLineWidth(2)
      context.setFontSize(20)
      let str = "签名区域";
      context.fillText(str, Math.ceil((width - context.measureText(str).width) / 2), Math.ceil(height / 2) - 20)
      context.draw()
    });
  },
  onShareAppMessage: (res) => {
    if (res.from === 'button') {
      console.log("来自页面内转发按钮");
      console.log(res.target);
    } else {
      console.log("来自右上角转发菜单")
    }
    return {
      title: '手动签名',
      path: '/pages/index/index?id=测试',
      // imageUrl: "/images/1.jpg",
      success: (res) => {
        console.log("转发成功", res);
      },
      fail: (res) => {
        console.log("转发失败", res);
      }
    }
  }
})