主要介绍了 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)
- 处理方式:将生成的图片,放在最上层,并设置透明度为 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;
但是在 IOS 手机上生成的图片,文字内容错位了
解决办法:诗中的每个字单独渲染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>