收藏
回答

使用Canvas导出图片的时候,第一次工作正常,第二次就卡死了,哪里搞错了呢?

基础库3.8.1,写了一段代码把几张图和文字画在画布上然后导出为图片。

第一次导出正常;第二次再导出的时候就卡住了,log显示到:“图片加载成功”,就没有了。

各位大佬看看哪里出了问题?小弟在这先谢过。。。

  exportItem: async function(e) {
    const index = e.currentTarget.dataset.index;
    const item = this.data.filteredList[index];
    
    if (!item) {
      wx.showToast({ title: '数据不存在', icon: 'error' });
      return;
    }


    wx.showLoading({ title: '正在导出...' });


    try {
      const dpr = wx.getWindowInfo().pixelRatio;
      const width = wx.getWindowInfo().screenWidth;
      const height = wx.getWindowInfo().screenHeight;


      // 创建离屏Canvas作为缓冲区
      const offscreenCanvas = wx.createOffscreenCanvas({
        type: '2d',
        width: width*dpr,
        height: 3000*dpr,
      });
      const offscreenCtx = offscreenCanvas.getContext('2d');
      offscreenCtx.scale(dpr, dpr);


      // 设置背景色
      offscreenCtx.fillStyle = '#FFF5E1';
      offscreenCtx.fillRect(0, 0, width, 3000);


      // 绘制标题
      offscreenCtx.font = 'bold 18px Arial';
      offscreenCtx.fillStyle = '#333333';
      offscreenCtx.fillText('详情', 20, 40);


      // 绘制描述文本
      let currentY = await this.drawText(offscreenCtx, item.storeDesc, width, 70);


      // 绘制图片
      if (item.imageList && item.imageList.length > 0) {
        currentY = await this.drawImages(offscreenCanvas, offscreenCtx, item.imageList, width, currentY + 20);
      }
      // 创建目标Canvas
      if (currentY > 3000) currentY=3000;


      const canvas = wx.createOffscreenCanvas({
        type: '2d',
        width: width*dpr,
        height: currentY*dpr,
      });
      const ctx = canvas.getContext('2d');
      ctx.scale(dpr, dpr);


      // 将离屏Canvas的内容复制到主Canvas
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(
        offscreenCanvas,
        0, 0,
        canvas.width, canvas.height,
        0, 0,
        canvas.width, canvas.height
      );


      // 等待一小段时间确保绘制完成
      await new Promise(resolve => setTimeout(resolve, 1000));


      // 导出图片
      await this.exportToImage(canvas);
    } catch (error) {
      console.error('导出失败:', error);
      wx.showToast({ title: '导出失败', icon: 'error' });
    } finally {
      wx.hideLoading();
    }
  },


  // 绘制文本
  async drawText(ctx, text, maxWidth, startY) {
    if (!text) return startY;


    ctx.font = '16px Arial';
    ctx.fillStyle = '#000000';
    const lineHeight = 24;
    let y = startY;
    const padding = 20;
    const maxTextWidth = maxWidth - padding * 2;


    const words = text.split('');
    let line = '';


    for (let n = 0; n < words.length; n++) {
      const testLine = line + words[n];
      const metrics = ctx.measureText(testLine);
      
      if (metrics.width > maxTextWidth && n > 0) {
        ctx.fillText(line, padding, y);
        line = words[n];
        y += lineHeight;
      } else {
        line = testLine;
      }
    }
    ctx.fillText(line, padding, y);
    return y + lineHeight;
  },


  // 绘制图片
  async drawImages(canvas, ctx, urls, canvasWidth, startY) {
    if (!urls || urls.length === 0) return startY;


    const padding = 20;
    const imageWidth = canvasWidth - padding * 2;
    let currentY = startY;


    for (const url of urls) {
      try {
        console.log('开始加载图片:', url);
        const res = await wx.getImageInfo({ src: url });
        console.log('图片加载成功:', res);
        
        const img = canvas.createImage();
        
        await new Promise((resolve, reject) => {
          img.onload = () => {
            console.log('图片绘制开始');
            const ratio = img.height / img.width;
            const imgHeight = imageWidth * ratio;
            
            // 绘制图片边框
            ctx.strokeStyle = '#cccccc';
            ctx.lineWidth = 1;
            ctx.strokeRect(padding, currentY, imageWidth, imgHeight);
            
            // 绘制图片
            ctx.drawImage(
              img,
              padding,
              currentY,
              imageWidth,
              imgHeight
            );
            
            console.log('图片绘制完成');
            currentY += imgHeight + padding;
            resolve();
          };
          img.onerror = (err) => {
            console.error('图片加载失败:', err);
            reject(err);
          };
          img.src = res.path;
        });
      } catch (err) {
        console.error('图片处理失败:', url, err);
      }
    }
    return currentY;
  },


  // 导出图片
  async exportToImage(canvas) {
    try {
      console.log('开始导出图片');
      const res = await wx.canvasToTempFilePath({
        canvas: canvas,
        x: 0,
        y: 0,
        width: canvas.width,
        height: canvas.height,
        destWidth: canvas.width,
        destHeight: canvas.height,
        fileType: 'png',
        quality: 1
      });
      
      console.log('图片导出成功,开始保存到相册');
      wx.previewImage({
        urls: [res.tempFilePath],
      });
    } catch (err) {
      console.error('导出失败:', err);
      if (err.errMsg && err.errMsg.includes('auth deny')) {
        wx.showModal({
          title: '提示',
          content: '需要相册权限才能保存图片',
          success: (res) => {
            if (res.confirm) wx.openSetting();
          }
        });
      } else {
        throw err;
      }
    }
  },
});


最后一次编辑于  05-09
回答关注问题邀请回答
收藏

1 个回答

  • 社区技术运营专员-Jahozheng
    社区技术运营专员-Jahozheng
    05-10

    你好,麻烦提供出现问题的具体机型、微信版本号、系统版本号,以及能复现问题的代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html)

    05-10
    有用
    回复
登录 后发表内容