html2canvas 能够实现浏览器端直接对整个或部分页面进行截屏,是目前较为常用的截屏方案,其原理简单来说就是先将需截屏的 DOM 部分转化为 canvas 画布,再将 canvas 画布转化为图片。html2canvas 的使用很简单,但在实际开发过程中,需注意如下几点:
图片跨域问题(截图中会出现图像缺失)
- 解决方案:
- 在 html2canvas 配置项中配置 allowTaint: false
canvas 的 CanvasRenderingContext2D 属于浏览器中的对象,如果曾经渲染过跨域资源,浏览器就认定 canvas 已经被污染(tainted)了。
- 在 html2canvas 配置项中配置 useCORS: true
重要的配置项,表示允许跨域资源共享,注意不能与 allowTaint 同时配置为 true。
- 在 img 标签中添加 crossOrigin = “anonymous”
anonymous:如果使用这个值的话就会在请求中的 header 中的带上 Origin 属性,但请求不会带上 cookie 和客户端 ssl 证书等其他的一些认证信息。
- 图片服务器配置 Access-Control-Allow-Origin: *
重要的配置项,是跨域问题的根本源泉,需后端配合。
生成的截图中文字间距变大
- 解决方案:
使用 CSS 属性 letter-spacing 进行调整。
能进行截图,但截图显示不完整
- 解决方案:
在截图操作前先将 body 的 scrollTop 值设为0(需提前确认所带来的体验差异)。
生成的图片模糊(截图锯齿化较为严重)
- 解决方案(原理:先将 canvas 容器扩大,再将合成的图片进行缩放):
// 动态获取设备的像素比,从而正确放大 canvas
getPixelRatio(context) {
let backingStore =
context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio ||
1;
return (window.devicePixelRatio || 1) / backingStore;
},
saveScreenshot() {
console.log("执行截屏");
let self = this,
canvas = document.createElement("canvas"),
width = document.getElementById("screenPart").clientWidth,
height = document.getElementById("screenPart").clientHeight,
context = canvas.getContext("2d"),
scale = this.getPixelRatio(context),
pageYOffset = window.pageYOffset;
canvas.width = width * scale;
canvas.height = height * scale;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
context.scale(scale, scale);
self.loadImage = true;
setTimeout(() => {
html2canvas(document.getElementById("screenPart"), {
logging: false,
tainttest: true,
background: null,
useCORS: true,
canvas: canvas,
scale: scale,
width: width,
height: document.body.scrollHeight,
windowWidth: document.body.scrollWidth,
windowHeight: document.body.scrollHeight,
onrendered: function(canvas) {
let picUrl = canvas.toDataURL("image/jpeg");
picUrl = picUrl.replace(/data:image\/jpeg/i, "data:image/png");
// 存入 localStorge 以便后续取用
window.localStorage.setItem("picUrl", picUrl);
}
});
}, 500);
}
渲染时出现白屏
- 解决方案(原理:将 base64 转成二进制流,资源会减小 1 到 1.5 倍):
function dataURLtoBlob (data_url) {
let arr = data_url.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
let blob = false;
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
try {
blob = new Blob([u8arr], { type: mime });
} catch (e) {}
return blob;
}
在小程序内嵌 H5 开发环境中,图片资源过大时,某些机型(常见于 ios)会实行限流,在渲染时,微信可能会直接白屏或提示“该小程序继续运行会影响微信的使用”,继而强制退出该小程序。
JPEG的黑屏问题
- 解决方案:缩减部分图片元素的体积和尺寸大小。
设置 html2canvas 输出格式为 jpeg 时,会有一定几率导致生成的图片包含大量的黑色块。
html2canvas 暂不支持的 CSS 样式属性
These CSS properties are NOT currently supported |
---|
background-blend-mode |
background-clip: text |
box-decoration-break |
repeating-linear-gradient() |
font-variant-ligatures |
mix-blend-mode |
writing-mode |
writing-mode |
border-image |
box-shadow |
filter |
zoom |