Draws SVG into canvas with image data URL

by Philip Rogers

HTML

<!DOCTYPE html>
<h2>Using SVG foreignObject to draw html into canvas.</h2>
<br>
SVG DOM:<br>
<svg id="source_svg" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="200" height="200">
    visited link info: <a href="https://google.com">google.com</a><br>
    form control:
    <input type="checkbox" checked></input>
    <textarea xmlns="http://www.w3.org/1999/xhtml" style="width: 100px; height: 50px;">
      This is some scrollable text inside a textarea, which is inside a foreignObject.
      Line 2
      Line 3
      Line 4
      Line 5
      Line 6
      Line 7
      Line 8
      Line 9
      Line 10
      Line 11
      Line 12
    </textarea>
    <br>
    cross-origin image: <img src="https://pr.gg/happy.png" style="width: 30px; height: 30px;">
  </foreignObject>
</svg>

<br>
Canvas:<br>
<canvas id="dest_canvas" width="200" height="200"></canvas>

<div id="readback_status"></div>

<script>
  const svgElement = document.getElementById('source_svg');
  const canvasElement = document.getElementById('dest_canvas');
  const statusDiv = document.getElementById('readback_status');
  const ctx = canvasElement.getContext('2d');

  // 1. Serialize the SVG element to an XML string.
  const svgString = new XMLSerializer().serializeToString(svgElement);

  // 2. Encode the string into a base64 data URL.
  const svgDataUrl = 'data:image/svg+xml;base64,' + btoa(svgString);

  // 3. Create an image and set its source to the data URL.
  const img = new Image();
  img.onload = function() {
    // 4. Once the image loads, draw it to the canvas.
    ctx.drawImage(img, 0, 0);

    // 5. Try to read pixel data from the canvas.
    try {
      // This will throw a security error because the canvas is tainted.
      ctx.getImageData(0, 0, 1, 1);
      statusDiv.textContent = 'Pixel readback is possible.';
    } catch (e) {
      statusDiv.textContent = 'Pixel readback is not possible.';
   ...