微信小程序画布canvas的使用

发布时间 2023-03-30 17:44:20作者: 新手上线
wxml部分:
<view class="container">
  <canvas class="canvas1" id="myCanvas" type="2d" disable-scroll="true" bindtouchstart="canvasStart"
     bindtouchmove="canvasMove" bindtouchend="canvasEnd" touchcancel="canvasEnd"></canvas>
</view>
<view class="qingchu" bindtap="canvasClear">清除</view>
<view class="wancheng" bindtap="finish">完成</view>

wxss部分:

.container{
  width: 100%;
  padding-bottom: 100rpx;
}
.canvas1{
  width: calc(100% - 40rpx);
  margin: 0 20rpx;
  height: 400rpx;
  border: 2rpx solid #7062eb;
}
.go{
  text-align: center;
  background-color: aqua;
  padding: 30rpx 0;
}
.qingchu{
  text-align: center;
  background-color: #ec8f16;
  padding: 20rpx 0;
}
.wancheng{
  text-align: center;
  background-color: #44c063;
  padding: 20rpx 0;
}

js部分:

const MAX_V = 1; // 最大书写速度
const MIN_V = 0; // 最小书写速度
const MAX_LINE_WIDTH = 6; // 最大笔画宽度
const MIN_LINE_WIDTH = 2; // 最小笔画宽度
const MAX_LINE_DIFF = .03; // 两点之间笔画宽度最大差异
let context = null; // canvas上下文
let lastPoint = null; // 包含上一点笔画信息的对象
Page({
  data: {
    drawn: false,
  },
  onShow: function (options) {
    this.canvasInit();
  },
  canvasInit: function () {
    wx.createSelectorQuery() 
    .select('#myCanvas') // 在 WXML 中填入的 id
    .fields({ node: true, size: true })
    .exec((res) => {
      console.log('89',res);
      res[0].node.width = res[0].width;
      res[0].node.height = res[0].height;
        context = res[0].node.getContext("2d")
    })

  },
  canvasMove: function (e) {
    this.setData({
      drawn: true
    })
    let currPoint = {
      x: e.changedTouches[0].x, // X坐标
      y: e.changedTouches[0].y, // Y坐标
      t: new Date().getTime(), // 当前时间
      w: (MAX_LINE_WIDTH + MIN_LINE_WIDTH) / 2 /*默认宽度 */
    };
    if (lastPoint) {
      currPoint.w = this.calcLineWidth(currPoint); // 重新赋值宽度,覆盖默认值 
      context.beginPath();
      context.strokeStyle = '#000';
      context.lineCap = 'round';
      context.lineJoin = 'round';
      context.lineWidth = currPoint.w;
      context.moveTo(lastPoint.x, lastPoint.y);
      context.lineTo(currPoint.x, currPoint.y);
      context.stroke();
      // context.draw(true);
    }
    lastPoint = currPoint; // 结束前保存当前点为上一点
  },
  // 计算当前点的宽度,书写速度越快,笔画宽度越小,呈现出笔锋的感觉(笑)
  calcLineWidth: function (currPoint) {
    let consuming = currPoint.t - lastPoint.t; // 两点之间耗时
    if (!consuming) return lastPoint.w; // 如果当前点用时为0,返回上点的宽度。
    let maxWidth = Math.min(MAX_LINE_WIDTH, lastPoint.w * (1 + MAX_LINE_DIFF)); // 当前点的最大宽度
    let minWidth = Math.max(MIN_LINE_WIDTH, lastPoint.w * (1 - MAX_LINE_DIFF * 3)); // 当前点的最小宽度,变细时速度快所以宽度变化要稍快
    let distance = Math.sqrt(Math.pow(currPoint.x - lastPoint.x, 2) + Math.pow(currPoint.y - lastPoint.y, 2)); // 两点之间距离
    let speed = Math.max(Math.min(distance / consuming, MAX_V), MIN_V); /*当前点速度*/
    let lineWidth = Math.max(Math.min(MAX_LINE_WIDTH * (1 - speed / MAX_V), maxWidth), minWidth); /* 当前点宽度 */
    return lineWidth;
  },
  canvasEnd: function (e) {
    lastPoint = null; // 每笔画完清除缓存
  },
  canvasClear: function () {
    this.setData({
      drawn: false
    })
    context.clearRect(0, 0, context.canvas.width, context.canvas.height);
    // context.draw(false);
  },
  // canvasOut: function () {
  //   wx.navigateBack({
  //     delta: 1,
  //   })
  // },
  finish: function () {
    if (!this.data.drawn) {
      return;
    }

    //由于新版的canvas的wx.canvasToTempFilePath方法一直报错,只能通过以下方式来获取签名图片
    const res = context.canvas.toDataURL("image/png");
    const qaa = res.replace(/^data:image\/\w+;base64,/, "");

    console.log('图片',res);
    console.log('图片',qaa);
    const fsm = wx.getFileSystemManager();
    console.log('图片2',fsm);
    const FILE_BASE_NAME = "tmp_base64src_" + new Date().getTime();
    // const FILE_BASE_NAME = "tmp_base64src_";
    console.log('图片3',FILE_BASE_NAME);
    const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.png`;
    console.log('图片4',filePath);
    fsm.writeFile({
      filePath,
      data: res.replace(/^data:image\/\w+;base64,/, ""),
      encoding: "base64",
      success: (res) => {
        console.log('完成',res);
          // this.getOpenerEventChannel().emit('signature', filePath); //传签名图片的临时路径回上一页
          // wx.navigateBack();
      },
      fail() {
        wx.showToast({ title: "生成签名失败", icon: "none" });
      },
    });
  },
})