html2canvas 问题解决汇总

5,992 阅读3分钟

主要介绍了 html2canvas 的基本使用及下载处理,也介绍了项目中使用的一些问题和解决方法,如初始化截图时机、跨域问题、滚动条问题、图片不清晰问题、多行文字错位等。

1. 基础介绍

Github 地址:github.com/niklasvh/ht…

html2canvas 是一个 JavaScript HTML 渲染器,允许在用户浏览器中直接对网页或部分网页进行“截图”。这些截图基于 DOM,因此可能与实际显示效果不完全一致,因为它并不是进行实际的截图,而是根据页面上的信息构建截图。

html2canvas 的主要用途是把网页渲染成图片,然后保存到本地。

// 引入
import html2canvas from "html2canvas";
// 基础使用
const generateImg = async () => {
    const canvas = await html2canvas(
      // 截图元素
      document.querySelector(".mlp_down") as HTMLElement,
      {
        useCORS: true, // 允许图片跨域,确保所有外部资源(如字体和图片)都支持跨域访问
        allowTaint: true, // 允许污染画布
        scrollY: 0, // 页面有滚动条,截图可能会出现问题,确保截图区域没有滚动条
        scrollX: 0,
      }
    );
    // 将canvas转换为base64图片数据
    const base64Img = canvas.toDataURL("image/jpeg", 1.0);
    return base64Img;
  };

2. 初始化截图

在 html2canvas 执行之前确保所有动态内容已经更新完毕,一般使用 setTimeout 或者 requestAnimationFrame 等方法确保内容更新完成。

useEffect(() => {
  if (isWx) {
    setTimeout(() => {
      // 生成截图
      generateImg();
    }, 100); // 等待 100ms 确保内容更新完成
  }
}, []);

3. 图片保存

上述生成图片后,需要保存到本地。

  • 手机浏览器中,可以直接下载
  • 微信浏览器中,不能直接下载,需要长按保存
    • 处理方式:将生成的图片,放在最上层,并设置透明度为 0(opacity:0)
const handleDownload = async () => {
  const base64Img = await generateImg();
  // 微信环境判断
  const isWx =
    window.navigator.userAgent.toLowerCase().indexOf("micromessenger") > -1;

  if (isWx) {
    message.info("请长按图片保存");
    // 微信环境
    return;
  }

  // 下载图片
  const link = document.createElement("a");
  link.href = base64Img;
  link.download = "藏头诗";
  link.style.display = "none";
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};

4. 图片不清晰问题

在手机端使用时,保存下来的图片很模糊,需要配置scale参数,消除截图锯齿。

  • window.devicePixelRatio:用于获取设备的像素比率(device pixel ratio),即物理像素与 CSS 像素的比例。这个属性通常用于适应高分辨率屏幕(例如 Retina 屏幕),以确保在不同设备上都能获得清晰的图像和文本。

    • 提高图片质量:在高分辨率屏幕上,使用 window.devicePixelRatio 可以使图像放大,从而提高截图的清晰度。
    • 适应不同设备:不同设备有不同的像素密度,通过 window.devicePixelRatio 可以自动适应不同的设备,确保截图在各种设备上都能清晰可见。
  • 物理像素:屏幕上的实际像素数量。

  • CSS 像素:浏览器用来计算布局的逻辑像素。

  • 设备像素比:物理像素与 CSS 像素的比例。

假设设备的 devicePixelRatio 为 2,物理像素为 1px,CSS 像素为 0.5px。

这意味着在高分辨率设备上,每个 CSS 像素实际上对应两个物理像素,因此图像会更加清晰。

const canvas = await html2canvas(
  document.querySelector(".mlp_down") as HTMLElement,
  {
    // 根据需要调整缩放比例,解决图片不清晰问题
    // 放大倍数,消除截图锯齿
    scale: window.devicePixelRatio,
  }
);

5. 多行文字错位问题

垂直展示诗歌内容时,在 Andriod 手机浏览器中生成的图片,文字内容显示正常;

  • 从右到左的垂直书写模式:writing-mode: vertical-rl;

html2canvas_1.png

但是在 IOS 手机上生成的图片,文字内容错位了

html2canvas_2.png

html2canvas_3.png

解决办法:诗中的每个字单独渲染span

<div className="mlp_poem">
  {poem.map((line, index) => (
    <div key={index} className="line">
      {/* 1. 改造前 */}
      {/* {line} */}

      {/* 2. 改造后:修复多行文字错位问题:每个字单独渲染 */}
      {line.split("").map((r: string) => (
        <span key={r}>{r}</span>
      ))}
    </div>
  ))}
</div>