Firstly, authorization is divided into three states: 0-unpulled authorization, 1-authorized, and 2-unauthorized. To set the page capacity to match Button’s open-type invocation, use computed to carry the value of permissionState with the variable openType.

When not authorized, click the button to jump to the permission setting page.

  computed: {
    openType: {
      require: ["permissionState"],
      fn({
        permissionState
      }) {
        return permissionState == 2 ? 'openSetting' : ' '; }}},Copy the code

In the XML

<button bindtap="checkPermission" open-type="{{openType}}">Save the picture</button>
Copy the code

During the life cycle show, update the authorization status so that it can be updated when you return from the permission Settings page

show: function() {
      // Update the authorization status
      wx.getSetting({
        success: (res) = > {
          this.setData({
            permissionState: checkPermission(res)
          })
        },
        fail: (err) = >{}})},Copy the code

CheckPermission function

// Returns the authorization status by querying authorization
function checkPermission(res) {
  let {
    authSetting
  } = res;
  let key = 'scope.writePhotosAlbum';

  return! authSetting.hasOwnProperty(key) ?0 : authSetting[key] ? 1 : 2
}
Copy the code

Except in the case of authorization failure click the button to judge permissions or pull, or draw.

checkPermission(res) {
      if (this.data.permissionState == 1) {
        // If authorized, draw directly
        this.drawCard();
      } else if (this.data.permissionState == 0) {
        // Pull the authorization window without authorization
        this.getPermission()
      }
},
Copy the code

Access to the album through wechat API

// pull authorization
    getPermission() {
      wx.authorize({
        scope: 'scope.writePhotosAlbum'.success: (a)= > {
          this.setData({
            permissionState: 1
          })
          this.drawCard()
        },
        fail: (a)= > {
          this.setData({
            permissionState: 2
          })
          wx.showToast({
            icon: 'none'.title: 'Authorization failed',})}})},Copy the code

Drawing canvas (omitting some elements)

drawCard() {
      let ctx = wx.createCanvasContext('canvas'.this)
      // Draw the background color
      ctx.setFillStyle('#ffffff')
      ctx.fillRect(0.15.240.390);
      // Create a home page
      let titleSrc = this.data.img;
      ctx.drawImage(titleSrc, 0.0.310.120);
      // Draw the chicken soup text
      drawMultiText(ctx, 'Today you may be far away from the peak, but by your efforts today, you have the strength to climb the peak tomorrow. '.40.280.32.215.'# 333333'.'normal 500 19px Source Han Sans CN')
      // Draw quotes
      drawText(ctx, ' ' '.'normal 800 25px Source Han Sans CN'.24.200.'#F48400')
      // Draw data
      ctx.draw(false, (res= > {
        setTimeout((a)= > {
          this.canvas2Img()
        }, 500)}})),Copy the code

Encapsulates methods for drawing text and multi-line text

// Text rendering
function drawText(ctx, str, font, x, y, color) {
  ctx.setFillStyle(color);
  ctx.font = font;
  ctx.fillText(str, x, y)
}
// Multi-line text drawing
//(context text x y line height fold line width color font)
function drawMultiText(ctx, str, leftWidth, initHeight, lineHeight, canvasWidth, color, font) {
  let lineWidth = 0;
  let lineNum = 0;
  let lastSubStrIndex = 0; // The index of the string each time it is truncated
  let titleHeight = 0;
  ctx.setFillStyle(color);
  ctx.font = font;
  for (let i = 0; i < str.length; i++) {
    lineWidth += ctx.measureText(str[i]).width;
    if (lineWidth > canvasWidth && lineNum < 4) {
      ctx.fillText(str.substring(lastSubStrIndex, i), leftWidth, initHeight); // Draw the intercept
      ++lineNum
      initHeight += lineHeight; // Height of the font
      lineWidth = 0;
      lastSubStrIndex = i;
      titleHeight += 30;
    }
    if (i == str.length - 1 && lineNum < 4) { // Draw the rest
      ctx.fillText(str.substring(lastSubStrIndex, i + 1), leftWidth, initHeight); }}// the title border-bottom line is the distance from the top
  titleHeight = titleHeight + 10;
  return titleHeight
}
Copy the code

Effect:

canvas2img

canvas2Img() {
      wx.canvasToTempFilePath(
        {
          x: 0.y: 0.width: 330.height: 440.destWidth: 660.destHeight: 880.canvasId: "canvas".success: res= > {
            this.saveAsFile(res.tempFilePath);
          },
          fail(err) {
            console.log(err); }},this
      );
    },
Copy the code

Save to album

saveAsFile(path) {
      wx.saveImageToPhotosAlbum({
        filePath: path, // This is the image path
        success: res= > {
          wx.showToast({
            icon: "none".title: "Saved successfully"
          });
        },
        fail: err= > {
          wx.showToast({
            icon: "none".title: "Save failed. Please try again later."
          });
        },
        complete: (a)= > {
          // Intercepting release
          this.setData({
            isDraw: false}); }}); },Copy the code

Business flow chart