html2canvas原理
有时候我们会碰到将部分的网页下载成图片的需求,我们会使用html2canvas将网页转换成图片,再将图片下载下来。那么大家知道html2canvas是如何将网页转换成图片的吗? 原理是先将html转成svg,在将svg转成img,最后将img绘制到canvas上。这样就可以下载图片了。
foreignObject
foreignObject是svg中一个特殊的元素。它允许在浏览器的上下文中,包含不同的XML命名空间,比如XHTML / HTML。 所以我们只要将html元素,原封不动的复制到foreignObject元素中,就可以获得一个svg了。
请看下面的例子:
function html2svg (width, height, x, y, node) {
const xmlns = 'http://www.w3.org/2000/svg';
const svg = document.createElementNS(xmlns, 'svg');
const foreignObject = document.createElementNS(xmlns, 'foreignObject');
svg.setAttributeNS(null, 'width', width.toString());
svg.setAttributeNS(null, 'height', height.toString());
foreignObject.setAttributeNS(null, 'width', '100%');
foreignObject.setAttributeNS(null, 'height', '100%');
foreignObject.setAttributeNS(null, 'x', x.toString());
foreignObject.setAttributeNS(null, 'y', y.toString());
foreignObject.setAttributeNS(null, 'externalResourcesRequired', 'true');
svg.appendChild(foreignObject);
foreignObject.appendChild(node);
return svg;
}
const warp = document.getElementById('warp');
const warpClone = warp.cloneNode(true);
const zoom = parseInt(input.value) || 1;
const svg = picture.html2svg((warp.offsetWidth * zoom) + 10, (warp.offsetHeight * zoom) + 10, 5, 5, warpClone);
document.body.appendChild(svg);
svg2img
想必很多同学已经想到了,image元素本来就是支持svg的。我们只要注意一点,html元素中的class样式,不要弄丢就可以了。
首先遍历html,然后使用getComputedStyle方法获取到html元素的样式。接下来设置到svg中,最后将svg转换成img/
例子:
function setCssStyle (node, zoom) {
if (node.children && node.children.length > 0) {
for (let i = 0, size = node.children.length; i < size; i++) {
setCssStyle(node.children.item(i));
}
}
// 第二个参数可以获取指定伪类的样式
const style = getComputedStyle(node, null);
node.style.cssText = style.cssText;
node.style.transformOrigin = '0 0';
node.style.transform = `scale(${ zoom })`;
node.className = '';
}
function svg2img (svg) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = `data:image/svg+xml;charset=utf-8,${ encodeURIComponent(new XMLSerializer().serializeToString(svg)) }`;
});
}
将img绘制到canvas中并下载
直接上代码
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// 默认是png格式
canvas.toBlob((blob) => {
// 下载blob
download(blob);
});
谢谢阅读