主要介绍了 html2canvas 的基本使用及下载处理,也介绍了项目中使用的一些问题和解决方法,如初始化截图时机、跨域问题、滚动条问题、图片不清晰问题、多行文字错位等。
1. 基础介绍
Github 地址:github.com/niklasvh/ht…
html2canvas
是一个 JavaScript HTML 渲染器,允许在用户浏览器中直接对网页或部分网页进行“截图”
。这些截图基于 DOM,因此可能与实际显示效果不完全一致,因为它并不是进行实际的截图,而是根据页面上的信息构建截图。
html2canvas
的主要用途是把网页渲染成图片,然后保存到本地。
1
2import html2canvas from "html2canvas";
3
4const generateImg = async () => {
5 const canvas = await html2canvas(
6
7 document.querySelector(".mlp_down") as HTMLElement,
8 {
9 useCORS: true,
10 allowTaint: true,
11 scrollY: 0,
12 scrollX: 0,
13 }
14 );
15
16 const base64Img = canvas.toDataURL("image/jpeg", 1.0);
17 return base64Img;
18 };
2. 初始化截图
在 html2canvas 执行之前确保所有动态内容已经更新完毕
,一般使用 setTimeout
或者 requestAnimationFrame
等方法确保内容更新完成。
1useEffect(() => {
2 if (isWx) {
3 setTimeout(() => {
4
5 generateImg();
6 }, 100);
7 }
8}, []);
3. 图片保存
上述生成图片后,需要保存到本地。
- 手机浏览器中,可以直接下载
- 微信浏览器中,不能直接下载,需要长按保存
- 处理方式:将生成的图片,放在最上层,并设置透明度为 0(
opacity:0
)
- 处理方式:将生成的图片,放在最上层,并设置透明度为 0(
1const handleDownload = async () => {
2 const base64Img = await generateImg();
3
4 const isWx =
5 window.navigator.userAgent.toLowerCase().indexOf("micromessenger") > -1;
6
7 if (isWx) {
8 message.info("请长按图片保存");
9
10 return;
11 }
12
13
14 const link = document.createElement("a");
15 link.href = base64Img;
16 link.download = "藏头诗";
17 link.style.display = "none";
18 document.body.appendChild(link);
19 link.click();
20 document.body.removeChild(link);
21};
4. 图片不清晰问题
在手机端使用时,保存下来的图片很模糊,需要配置scale
参数,消除截图锯齿。
-
window.devicePixelRatio
:用于获取设备的像素比率(device pixel ratio),即物理像素与 CSS 像素的比例。这个属性通常用于适应高分辨率屏幕(例如 Retina 屏幕),以确保在不同设备上都能获得清晰的图像和文本。- 提高图片质量:在高分辨率屏幕上,使用 window.devicePixelRatio 可以使图像放大,从而提高截图的清晰度。
- 适应不同设备:不同设备有不同的像素密度,通过 window.devicePixelRatio 可以自动适应不同的设备,确保截图在各种设备上都能清晰可见。
-
物理像素:屏幕上的实际像素数量。
-
CSS 像素:浏览器用来计算布局的逻辑像素。
-
设备像素比:物理像素与 CSS 像素的比例。
假设设备的 devicePixelRatio 为 2,物理像素为 1px,CSS 像素为 0.5px。
这意味着在高分辨率设备上,每个 CSS 像素实际上对应两个物理像素,因此图像会更加清晰。
1const canvas = await html2canvas(
2 document.querySelector(".mlp_down") as HTMLElement,
3 {
4
5
6 scale: window.devicePixelRatio,
7 }
8);
5. 多行文字错位问题
垂直展示诗歌内容时,在 Andriod 手机浏览器中生成的图片,文字内容显示正常;
- 从右到左的垂直书写模式:
writing-mode: vertical-rl;
但是在 IOS 手机上生成的图片,文字内容错位了
解决办法:诗中的每个字单独渲染span
1<div className="mlp_poem">
2 {poem.map((line, index) => (
3 <div key={index} className="line">
4 {/* 1. 改造前 */}
5 {/* {line} */}
6
7 {/* 2. 改造后:修复多行文字错位问题:每个字单独渲染 */}
8 {line.split("").map((r: string) => (
9 <span key={r}>{r}</span>
10 ))}
11 </div>
12 ))}
13</div>