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

使用jsPDF和html2canvas无法打印带CSS滤镜的图片

问题根源

html2canvas 对 CSS filter: grayscale() 的支持存在局限性,Tailwind 的 grayscale 类本质就是这个CSS属性,当你用html2canvas捕获DOM时,它可能无法正确解析并应用这个滤镜效果,导致生成的canvas还是彩色,最终PDF里的图片自然也保持彩色。

解决方法

下面提供几种可行的修复方案,按推荐程度排序:

方案1:生成Canvas后手动灰度化

在html2canvas生成canvas之后,通过Canvas API直接修改像素数据,将图片转为灰度。这种方法不需要修改原DOM结构,直接处理最终的canvas即可。

修改你的handlePrint函数:

const handlePrint = async () => {
    const grid = document.getElementById('image-grid');
    const canvas = await html2canvas(grid);

    // 手动处理灰度化
    const ctx = canvas.getContext('2d');
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;

    for (let i = 0; i < data.length; i += 4) {
        // 计算标准灰度值:Y = 0.299*R + 0.587*G + 0.114*B
        const gray = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114;
        data[i] = gray;     // 红色通道
        data[i + 1] = gray; // 绿色通道
        data[i + 2] = gray; // 蓝色通道
        // alpha通道保持不变
    }

    ctx.putImageData(imageData, 0, 0);

    const imgData = canvas.toDataURL('image/png');

    // 后续PDF生成代码保持不变
    const pdf = new jsPDF({
      orientation: 'portrait',
      unit: 'pt',
      format: 'a4'
    });

    const pdfWidth = pdf.internal.pageSize.getWidth();
    const pdfHeight = pdf.internal.pageSize.getHeight();

    const imgWidth = pdfWidth;
    const imgHeight = (canvas.height * imgWidth) / canvas.width;

    const spaceForText = imgHeight;
    const adjustedImgHeight = imgHeight - spaceForText;

    const x = 0;
    const y = (pdfHeight - adjustedImgHeight) / 2;

    pdf.addImage(imgData, 'PNG', 20, 20, 555, 555);

    const text = "Your Text Here";
    const textHeight = 12;
    const textY = (pdfHeight + adjustedImgHeight) / 2 + 20;

    const textWidth = pdf.getTextWidth(text);
    const centerX = (pdfWidth - textWidth) / 2;
    pdf.setFont("Helvetica", "normal");
    pdf.setFontSize(25);
    pdf.text(text, centerX - 10, 650);

    pdf.autoPrint();
    window.open(pdf.output('bloburl'));
};

方案2:提前将图片转为灰度图再渲染

在组件加载图片时,先通过Canvas将图片转为灰度格式,替换原图片的src,这样html2canvas捕获的DOM本身就是灰度图,自然能生成正确的PDF。

修改你的ImagePreviewModal组件:

const ImagePreviewModal = ({ selectedImages }) => {
  const [items, setItems] = useState([]);

  useEffect(() => {
    const convertToGrayscale = async (imageSrc) => {
      return new Promise((resolve) => {
        const img = new Image();
        img.crossOrigin = 'anonymous'; // 处理跨域图片,同域图片可移除该行
        img.src = imageSrc;
        img.onload = () => {
          const canvas = document.createElement('canvas');
          canvas.width = img.width;
          canvas.height = img.height;
          const ctx = canvas.getContext('2d');
          // 绘制原图并应用灰度滤镜
          ctx.filter = 'grayscale(100%)';
          ctx.drawImage(img, 0, 0);
          resolve(canvas.toDataURL('image/png'));
        };
      });
    };

    const processImages = async () => {
      const processed = await Promise.all(
        selectedImages.map(async (img) => ({
          ...img,
          imageSrc: await convertToGrayscale(img.imageSrc)
        }))
      );
      setItems(processed);
    };

    processImages();
  }, [selectedImages]);

  return (
    <div id="image-grid">
      {items.map((image, index) => (
        <div className="w-full h-auto ">
          <div className='grid grid-cols-2 gap-3 my-1 px-7 py-4 rounded-md '>
            <img
              src={image.imageSrc}
              alt={`Selected ${index + 1}`}
              className="w-full h-auto rounded-sm border border-white"
            />
            <img
              src={image.imageSrc}
              alt={`Selected ${index + 2}`}
              className="w-full h-auto rounded-sm border border-white"
            />
          </div>
        </div>
      ))}
    </div>
  );
};

方案3:配置html2canvas支持CSS滤镜

部分较新版本的html2canvas支持通过配置项启用滤镜解析,你可以尝试在调用html2canvas时添加如下配置:

const canvas = await html2canvas(grid, {
  useCORS: true,
  allowTaint: true,
  logging: true // 可选,用于调试是否成功捕获滤镜
});

不过这个方案兼容性不稳定,不同浏览器和html2canvas版本可能表现不一致,优先推荐前两种方案。

内容的提问来源于stack exchange,提问作者Anshu Patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:36:19