将文章保存为图片
1. 使用html2canvas
将dom转成canvas,转成图片数据,再使用a标签实现下载。
html2canvas(dom).then(canvas => {
const dataUrl = canvas.toDataURL('image/png');
const a = document.createElement('a');
a.href = dataUrl;
a.download = '文章.png';
a.click();
});
2. 图片丢失
需要将内容中的<img>内容从url转成base64。
function imgUrl2Base64(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = url;
// 必须设置允许跨域
img.crossOrigin = '*';
img.onload = function () {
const canvas = document.createElement('canvas');
const { width, height } = img;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
const dataUrl = canvas.toDataURL('image/png');
resolve(dataUrl);
};
img.onerror = reject;
});
}
注意
若未设置img.crossOrigin = '*',则会报错:
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
3.将dom节点下所有图片链接替换成base64
function handleImgsInNode(node) {
const imgs = [...node.querySelectorAll('img')];
return Promise.all(imgs.map(img => imgUrl2Base64(img.src))).then(list => {
imgs.forEach((img, i) => (img.src = list[i]));
});
}
4.问题
由于有些文章的dom节点较大,导致生成canvas的过程较长,占据主线程。并且由于依赖dom,无法使用web worker来提速。