将页面内容保存为图片

330 阅读1分钟

将文章保存为图片

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来提速。