📸

DOMをSVGパワーで丸ごと画像にするやつの自力実装例

2023/02/03に公開約1,500字

これは何ですか?

DOMを丸ごとforeignObjectで包んで画像にするコードのプロトタイプです
デモページではcontenteditableな<div>に貼り付けてキャプチャできます
僕自身vscodeの成果物を画像化してツイートする等で何回か使いましたが、肝心のツイッターが凍結してしまいました(異議申し立て済)

👆こんな感じで一発キャプチャできました
HTML全文 | デモ

const captureDOM = (selector, sendTo) => {
  let dom = document.querySelector(selector);
  let width = dom.clientWidth;
  let height = dom.clientHeight;
  console.log("capturing");
  let svgData = `
    <svg id="captureSVG" width="${width}" height="${height}">
      <foreignObject width="${width}" height="${height}" x="0" y="0">
        ${dom.innerHTML}
      </foreignObject>
    </svg>
  `;
  let cvs = document.getElementById("result");
  cvs.width = width;
  cvs.height = height;
  let c2d = cvs.getContext('2d');
  let data = new DOMParser().parseFromString(svgData, "text/html");
  let img = new Image();
  img.src = `
    data:image/svg+xml;base64,${
      window.btoa(
        unescape(
          encodeURIComponent(
	    new XMLSerializer().serializeToString(data.querySelector("#captureSVG"))
	  )
        )
      )
    }
  `;
  img.onload = () => {
    c2d.clearRect(0, 0, width, height);
    c2d.drawImage(img, 0, 0, width, height);
    document.querySelector(sendTo).src = cvs.toDataURL();
  };
};

課題点

  • リンクで埋め込んだ<img>が読み込まれる前に即drawImage()が発動するので、一度パースしてfetch後base64エンコードする等の措置が欲しいです

Discussion

ログインするとコメントできます