收藏
回答

使用wx.saveImageToPhotosAlbum保存图片到本地,为什么有时候会出现空白图片?

目前调用canvasToTempFilePath绘制canvas,正常返回图片地址,并展示。图片地址:http://tmp/kdGi1n6uNhrp04f4a9e26b0100eb9d363d91e17f7b49.png

然后调用saveImageToPhotosAlbum将图片保存到相册,会出现中间的二维码空白的情况,比如VIVO手机、华为手机都出现过,微信版本都是最新的,是什么原因呢?

回答关注问题邀请回答
收藏

2 个回答

  • Cjiang
    Cjiang
    发表于移动端
    2021-04-27
    你好,麻烦提供出现问题的具体机型、微信版本号、系统版本号,以及能复现问题的代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html),并提供下复现的视频(上传至腾讯视频 https://v.qq.con)
    2021-04-27
    有用
    回复
  • Z
    Z
    2021-04-26

    提供个代码片段?

    2021-04-26
    有用
    回复 3
    • 张冬冬
      张冬冬
      2021-04-26
      不知道为什么绘制没问题,下载却部分有问题
      2021-04-26
      回复
    • Z
      Z
      2021-04-26回复张冬冬
      这样我也看不出来什么问题啊  简单搞个可以复现代码片段https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html
      2021-04-26
      回复
    • 张冬冬
      张冬冬
      2021-04-26
      代码依赖的类太多了,这是封装的类库
      import utils from "../utils";
      /**
       * 通用Canvas类
       * Created by dongdongzhang on 2020-02-09.
       */
      class BaseCanvas {
          /**
           * 构造函数
           */
          constructor() {
          }
          /**
           * 将当前画布的内容导出生成图片,并返回文件路径
           * @param canvas canvas对象
           * @param width 宽度
           * @param height 高度
           * @param callBack 回调函数
           * @param failCallBack 失败回调函数
           */
          canvasToTempFilePath(canvas, width, height, callBack, failCallBack) {
              //微信
              //#ifdef MP-WEIXIN
              setTimeout(() => {
                  uni.canvasToTempFilePath({
                      width: width,
                      height: height,
                      destWidth: canvas.width,
                      destHeight: canvas.height,
                      canvas: canvas,
                      success: res => {
                          if (callBack) {
                              callBack(res.tempFilePath);
                          }
                      },
                      fail: res => {
                          if (failCallBack) {
                              failCallBack(res);
                          }
                      }
                  });
              }, 500);
              //#endif
              //支付宝
              //#ifdef MP-ALIPAY
              canvas.draw();
              setTimeout(() => {
                  canvas.toTempFilePath({
                      width: width,
                      height: height,
                      destWidth: canvas.width,
                      destHeight: canvas.height,
                      canvas: canvas,
                      success: res => {
                          if (callBack) {
                              callBack(res.filePath);
                          }
                      },
                      fail: res => {
                          if (failCallBack) {
                              failCallBack(res);
                          }
                      }
                  });
              }, 500);
              //#endif
          }
          /**
           * 绘制图片
           * @param canvas canvas对象
           * @param ctx canvas内容context
           * @param imgUrl 图片地址
           * @param x 起始点X
           * @param y 起始点Y
           * @param w 图片宽度
           * @param h 图片高度
           * @param fillet 圆角半径
           */
          drawImage(canvas, ctx, imgUrl, x, y, w, h, fillet, callback) {
              let drawCircleImg = (img) => {
                  ctx.beginPath();
                  ctx.save();
                  ctx.lineWidth = 1;
                  ctx.strokeStyle = 'transparent';
                  ctx.moveTo(x + fillet, y);// 创建开始点
                  ctx.lineTo(x + w - fillet, y);// 创建水平线
                  ctx.arcTo(x + w, y, x + w, y + fillet, fillet);// 创建弧
                  ctx.lineTo(x + w, y + h - fillet);// 创建垂直线
                  ctx.arcTo(x + w, y + h, x + w - fillet, y + h, fillet);// 创建弧
                  ctx.lineTo(x + fillet, y + h);// 创建水平线
                  ctx.arcTo(x, y + h, x, y + h - fillet, fillet);// 创建弧
                  ctx.lineTo(x, y + fillet);// 创建垂直线
                  ctx.arcTo(x, y, x + fillet, y, fillet);// 创建弧
                  ctx.stroke();
                  ctx.clip();
                  ctx.drawImage(img, x, y, w, h);
                  ctx.restore();
                  ctx.closePath();
              };
              //微信
              //#ifdef MP-WEIXIN
              const imgInfo = canvas.createImage();
              imgInfo.src = imgUrl;
              imgInfo.onload = () => {
                  if (fillet && fillet > 0) {
                      if (callback) {
                          callback();
                      }
                      drawCircleImg(imgInfo);
                  } else {
                      ctx.drawImage(imgInfo, x, y, w, h);
                      ctx.restore();
                      if (callback) {
                          callback();
                      }
                  }
              };
              //#endif
              //支付宝
              //#ifdef MP-ALIPAY
              if (fillet && fillet > 0) {
                  drawCircleImg(imgUrl);
              } else {
                  ctx.drawImage(imgUrl, x, y, w, h);
                  //绘制图片时,保存以绘制的画布(true)
                  ctx.draw(true);
              }
              //#endif
          }
          /**
           * 获取canvas对象
           * @param pageObj
           * @param canvasId
           * @param width
           * @param height
           * @returns {Promise<any>}
           */
          getCanvas(pageObj, canvasId, width, height) {
              let dpr = utils.public.getSystemInfoSync().pixelRatio;
              return new Promise((resolve) => {
                  //微信
                  //#ifdef MP-WEIXIN
                  pageObj.createSelectorQuery()
                      .select(`#${canvasId}`)
                      .fields({node: true, size: true})
                      .exec(res => {
                          const canvas = res[0].node,
                              ctx = canvas.getContext('2d');
                          canvas.width = width * dpr;
                          canvas.height = height * dpr;
                          ctx.scale(dpr, dpr);
                          resolve({canvas, ctx});
                      });
                  //#endif
                  //支付宝
                  //#ifdef MP-ALIPAY
                  const canvas = my.createCanvasContext(canvasId);
                  canvas.width = width * dpr;
                  canvas.height = height * dpr;
                  canvas.scale(1, 1);
                  resolve({canvas, ctx: canvas});
                  //#endif
              });
          }
          /**
           * 删除存储的文件数据
           */
          removeSavedFile() {
              uni.getSavedFileList({
                  success: res => {
                      res.fileList.forEach((val, key) => {
                          //删除存储的垃圾数据
                          uni.removeSavedFile({
                              //#ifdef MP-WEIXIN
                              filePath: val.filePath,
                              //#endif
                              //支付宝
                              //#ifdef MP-ALIPAY
                              apFilePath: val.apFilePath
                              //#endif
                          });
                      })
                  }
              });
          }
          /**
           * 绘制圆角矩形
           * @param {CanvasContext} ctx canvas上下文
           * @param {number} x 圆角矩形选区的左上角 x坐标
           * @param {number} y 圆角矩形选区的左上角 y坐标
           * @param {number} w 圆角矩形选区的宽度
           * @param {number} h 圆角矩形选区的高度
           * @param {number} r 圆角的半径
           * @param {number} fill 填充色
           */
          fillRoundRect(ctx, x, y, w, h, r, fill) {
              // 开始绘制
              ctx.beginPath();
              // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
              // 这里是使用 fill 还是 stroke都可以,二选一即可
              ctx.fillStyle = fill;
              //ctx.setStrokeStyle('#000')
              // 左上角
              ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
              // border-top
              ctx.moveTo(x + r, y);
              ctx.lineTo(x + w - r, y);
              ctx.lineTo(x + w, y + r);
              // 右上角
              ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
              // border-right
              ctx.lineTo(x + w, y + h - r);
              ctx.lineTo(x + w - r, y + h);
              // 右下角
              ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
              // border-bottom
              ctx.lineTo(x + r, y + h);
              ctx.lineTo(x, y + h - r);
              // 左下角
              ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
              // border-left
              ctx.lineTo(x, y + r);
              ctx.lineTo(x + r, y);
              // 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
              ctx.fill();
              // ctx.stroke()
              ctx.closePath()
          }
          /**
           * 绘制文本
           * @param ctx
           * @param word 文本内容
           * @param x 起始点X
           * @param y 起始点Y
           * @param fontStyle 字体样式
           * @param fillStyle 字体颜色
           * @param textAlign 字体对齐
           */
          fillText(ctx, word, x, y, fontStyle, fillStyle, textAlign) {
              if (fontStyle) {
                  ctx.font = fontStyle;
              }
              if (fillStyle) {
                  ctx.fillStyle = fillStyle;
              }
              if (textAlign) {
                  ctx.textAlign = textAlign;
              }
              ctx.fillText(word, x, y);
          }
          /**
           * 文字换行
           * @param ctx
           * @param str 文本
           * @param initX 起始点X
           * @param initY 起始点Y
           * @param lineHeight 行高
           * @param maxWidth 最大宽度
           * @param margin 文本距离到边界的距离
           */
          fillTextWrap(ctx, str, initX, initY, lineHeight, maxWidth, margin) {
              let lineWidth = 0;
              let canvasWidth = maxWidth ? maxWidth : 240;
              let lastSubStrIndex = 0;
              if (!lineHeight) {
                  lineHeight = 20;
              }
              for (let i = 0; i < str.length; i++) {
                  lineWidth += ctx.measureText(str[i]).width;
                  if (lineWidth > canvasWidth - margin * 2) {//减去保护边界,防止边界出现的问题
                      ctx.fillText(str.substring(lastSubStrIndex, i), initX, initY);
                      initY += lineHeight;
                      lineWidth = 0;
                      lastSubStrIndex = i;
                  }
                  if (i == str.length - 1) {
                      ctx.fillText(str.substring(lastSubStrIndex, i + 1), initX, initY);
                  }
              }
          }
      }
      export default BaseCanvas
      2021-04-26
      回复
登录 后发表内容