You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer生成PDF时图表Canvas渲染异常求助

Puppeteer生成PDF时Canvas图表显示异常的解决方案

问题描述

使用Puppeteer将HTML生成PDF时,Canvas图表在普通HTML页面和Puppeteer截图中渲染正常,但生成的PDF内显示异常。以下是我的代码:

const puppeteer = require('puppeteer');

class Webpage {
    static async generatePDF() {
        const browser = await puppeteer.launch({headless: true, args: ['--no-sandbox', '--ignore-certificate-errors'], ignoreDefaultArgs: ['--disable-extensions']});
        let page = await browser.newPage();

        await page.setViewport({width: 1280, height: 960, deviceScaleFactor: 1});
        await page.goto("url", { waitUntil: 'networkidle0', timeout: 30000 });
        await page.screenshot({path: "./screenshot.png"});
        
        const config = {
            path: '/home/haltdos/test.pdf',
            format: 'A3',
            printBackground: true,
            margin: {
                top: '3cm',
                bottom: '1cm',
                left: '1cm',
                right: '1cm'
            }
        };

        await page.emulateMediaType('screen');
        await page.pdf(config);
        await browser.close();
    }
}

Webpage.generatePDF();

解决方案

1. 等待Canvas完全渲染完成

networkidle0仅等待网络请求停止,无法确保Canvas异步绘制完成。添加针对性等待:

  • 基础等待方式:
    // 等待Canvas元素加载
    await page.waitForSelector('canvas');
    // 额外等待2秒确保绘制完成(可根据图表复杂度调整时长)
    await page.waitForTimeout(2000);
    
  • 精确等待(以Chart.js为例):
    await page.evaluate(() => {
      return new Promise(resolve => {
        if (window.chartInstance) {
          // 等待图表渲染完成
          window.chartInstance.rendered.then(resolve);
        } else {
          // 监听自定义的图表就绪事件
          document.addEventListener('chartReady', resolve);
        }
      });
    });
    

2. 切换到新版Headless模式

旧版Headless模式对Canvas的渲染支持存在局限性,改用新版模式:

const browser = await puppeteer.launch({
  headless: 'new', // 启用新版无头模式
  args: ['--no-sandbox', '--ignore-certificate-errors'],
  ignoreDefaultArgs: ['--disable-extensions']
});

3. 调整emulateMediaType的执行时机

将媒体类型模拟提前到页面加载前,确保页面以屏幕模式渲染:

await page.emulateMediaType('screen');
await page.goto("url", { waitUntil: 'networkidle0', timeout: 30000 });

4. 优化Canvas分辨率适配PDF

PDF生成的缩放逻辑可能导致Canvas显示异常,强制提升Canvas分辨率:

await page.evaluate(() => {
  const canvas = document.querySelector('canvas');
  if (canvas) {
    const scale = 2; // 2倍分辨率适配PDF
    const originalWidth = canvas.width;
    const originalHeight = canvas.height;
    
    canvas.width = originalWidth * scale;
    canvas.height = originalHeight * scale;
    canvas.style.width = `${originalWidth}px`;
    canvas.style.height = `${originalHeight}px`;
    
    // 如果使用图表库,触发重新绘制
    if (window.chartInstance) {
      window.chartInstance.resize();
    }
  }
});

5. 修正代码语法问题

原代码中config对象的margin属性缩进错误,已在上方代码示例中修正,确保对象结构合法。


内容的提问来源于stack exchange,提问作者Amish Thekke Parambil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:50:43