收藏
回答

Canvas-2D绘制并保存到相册,图片空白?

需求:使用canvas-2d绘制用户头像昵称,小程序码生成相应图片海报

异常:某些ios机型绘制保存后的图片为空白图片

手机型号:iphone8;系统版本:ios11.3 ;微信:7.0.15

手机型号:iPhone11 Pro Max;系统版本:13.2.3

手机型号:iPhoneX max  ; ios:13.6 ;微信版本:7.0.15

api使用:wx.downloadFile;wx.canvasToTempFilePath;wx.saveImageToPhotosAlbum

wxml

 <canvas style="position: absolute;top:0;left:100%;width: 750px;height: 1206px;" canvas-id='canvas'></canvas>

方法封装

const scopeName = {
  "userInfo": "用户信息",
  "userLocation": "地理位置",
  "address": "通讯地址",
  "invoiceTitle": "发票抬头",
  "invoice": "发票",
  "werun": "微信运动步数",
  "record": "录音功能",
  "writePhotosAlbum": "保存到相册",
  "camera": "摄像头"
};
const authorize = (scope) => {
  return new Promise((resolve, reject) => {
    const failText = `须授权${scopeName[scope]}!`;
    wx.getSetting({
      success(res) {
        if (res.authSetting[`scope.${scope}`]) {
          resolve(true);
        } else {
          wx.authorize({
            scope: `scope.${scope}`,
            success() {
              resolve(true);
            },
            fail() {
              wx.showModal({
                title: "提示",
                content: `检测到未打开${scopeName[scope]}权限`,
                confirmText: "授权",
                success(res) {
                  if (res.confirm) {
                    wx.openSetting({
                      success(res) {
                        if (res.authSetting[`scope.${scope}`]) {
                          resolve(true);
                        } else {
                          reject(failText);
                        }
                      }
                    });
                  } else {
                    reject(failText);
                  }
                },
                fail() {
                  reject(failText)
                }
              });
            },
          });
        }
      },
      fail() {
        reject(failText);
      }
    });
  });
};
const saveImageToPhotosAlbum = (filePath) => {
  return new Promise((resolve, reject) => {
    wx.saveImageToPhotosAlbum({
      filePath,
      success(res) {
        resolve(res);
      },
      fail() {
        reject();
      },
    });
  });
};
const saveImage = (url, type = 'online') => {
  return new Promise(async (resolve, reject) => {
    const isAuth = await await authorize("writePhotosAlbum").catch(err => {
      reject(err);
    });
    if (isAuth) {
      let tempFilePath = url;
      if (type === 'online') {
        tempFilePath = await downloadFile(url).catch(err => {
          reject('图片下载失败')
        });
      }
      const val = await saveImageToPhotosAlbum(tempFilePath).catch(err => {
        reject('取消保存');
      })
      if (val) {
        resolve(true);
      } else {
        reject();
      }
    } else {
      reject('无授权');
    }
  })
};

/**canvas保存图片 */
const canvasToTempFilePath = (params, component) => {
  return new Promise((resolve, reject) => {
    wx.canvasToTempFilePath({
      ...params,
      success(res) {
        resolve(res);
      },
      fail(res) {
        reject();
      },
    }, component)
  });
}

逻辑

 /**获取海报 */
createPoster(bg, qrcode, avatar, nickName) {
      return new Promise(async (resolve, reject) => {
        if (!bg || !qrcode || !avatar) return reject('图片资源异常');
        const ctx = wx.createCanvasContext("canvas", this); //获取画布
        //画海报
        ctx.drawImage(bg, 0, 0, 750, 1206);
        //画小程序码
        ctx.drawImage(qrcode, 466, 937, 202, 202);
        //画昵称
        ctx.font = '22px PingFangSC-Regular'
        ctx.setFillStyle('#6C3511');
        ctx.fillText(nickName, 198, 1000);
        //画头像
        const avatarInfo = {
          space: 78,
          x: 98,
          y: 971
        }
        ctx.save();
        ctx.beginPath();
        ctx.arc(avatarInfo.x + avatarInfo.space / 2, avatarInfo.y + avatarInfo.space / 2, avatarInfo.space / 2, 0, Math.PI * 2, false);
        ctx.clip();
        ctx.drawImage(avatar, avatarInfo.x, avatarInfo.y, avatarInfo.space, avatarInfo.space);
        ctx.restore();
        ctx.draw();
        const dpr = wx.getSystemInfoSync().pixelRatio || 1;
        setTimeout(async () => {
          const res = await canvasToTempFilePath({
            x: 0,
            y: 0,
            width: 750 * dpr,
            height: 1026 * dpr,
            destWidth: 750 * dpr,
            destHeight: 1206 * dpr,
            canvasId: "canvas",
            fileType: "jpg",
          }, this);
          if (res && res.tempFilePath) {
            resolve(res.tempFilePath);
          } else {
            reject('画板异常');
          }
        }, 200)
      });
    },

  async onShareImage() {
      wx.showLoading({
        title: '正在生成图片',
        mask: true
      });
      try {
        let bgData = "/assets/images/share/background.jpg";

        const nickName="昵称";

        const qrcodeUrl="";//二维码网络地址(已加入白名单)

        const avatar="";//用户头像网络地址(已加入白名单)

        const text = nickName.length > 10 ? `${nickName.substring(0,9)}...` : nickName;

        const avatarData = await downloadFile(avatar); //头像

        const qrcodeData = await downloadFile(qrcodeUrl); //小程序码数据

        const posterData = await this.createPoster(bgData, qrcodeData, avatarData, text); //生成海报数据

        const result = await saveImage(posterData, "file"); //保存图片

        if (result) {
          wx.hideLoading();
          wx.showToast({
            title: "图片已保存",
            mask: true
          });
        }
      } catch (error) {
        wx.hideLoading();
        wx.showToast({
          icon: "none",
          title: `分享图片生成失败!${error}`,
          mask: true
        });
      }
    },
回答关注问题邀请回答
收藏

3 个回答

登录 后发表内容
问题标签