问题描述:
如图所示,本次踩的坑,就是对于跨域的图片,虽然它可以正常渲染到页面上,但是 html2canvas 却没法正常“截图”,截到的结果是空的,和预期不符。
左侧容器中有一张图片 img1,但是该图片的 src 的值被浏览器判定为跨域了。(并且服务端也没进行额外处理)但是对于跨域的图片资源,浏览器想要把图片给正常渲染出来,完全是没问题的。问题出在对于跨域的图片资源,html2canvas 没法完成拍照。当我们使用 html2canvas 去拍照的时候,跨域的图片会被自动忽略……
背景知识:对于 img 元素,它的 src 属性,除了可以是一个 url,还可以是一坨 base64 格式的字符串。当我们获取到一张图片的 url 时,就有办法通过 js 来将其转为 base64 格式。
解决方案:将获取到的跨域的 url,转为 base64,然后再使用 html2canvas 来截图,此时就可以正常截取了。
<!-- img1 图片正常渲染,但是 html2canvas 没法正常截图 -->
<img src="跨域 url" />
<!-- img2 图片正常渲染,且 html2canvas 可以正常截图 -->
<img src="base64" />
/**
* 将 url 转为 base64
* @param {String} src 跨域图片的 url
* @param {String} cb 成功将 url 转为 base64 之后的回调
*/
function iamgeToBase64(src, cb) {
// 新建一个 Image 实例,去加载图片
const imgIns = new Image();
imgIns.crossOrigin = ""; // 解决跨域问题
imgIns.src = src;
// 图片加载完成后,使用 canvas 将其画出来,并转为 base64 格式
imgIns.onload = () => {
const canvas = document.createElement("canvas");
canvas.width = imgIns.width;
canvas.height = imgIns.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(imgIns, 0, 0, imgIns.width, imgIns.height);
const ext = imgIns.src
.substring(imgIns.src.lastIndexOf(".") + 1)
.toLowerCase();
cb(canvas.toDataURL("image/" + ext));
};
}
小结:「跨域导致渲染出空白图片的问题」上述方案可以解决该问题,但是具体原理并不了解,先知道咋解决就好。
- 不熟悉 canvas
- 不知道 base64 是啥,只知道它可以作为 img 的 src 来使