DOM to Canvas

by fxi

HTML

<div id="content">
  <div class="framed-dotted">
    <em>This</em> is <span class="framed">HTML</span> drawn into <strong>canvas</strong>
  </div>
</div>
<img id="out">

CSS

.framed-dotted {
  border: 2px dotted #f73;
  font: 12px sans-serif;
}

.framed {
  color: #00f;
  border: 1px solid #777;
  padding: 0 4px;
  font-size: 16px;
}

JavaScript

//https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas


htmlToData({
  selector: "#content",
  scale: 10,
  callback: function(canvas) {
    img = new Image;
    img.onload = function(){
     document.body.appendChild(this);
    };
    img.src = canvas.toDataURL();
  }
})

/**
 * htmlToData 
 * @param {Object} o Options
 * @param {String|Element} o.selector Selector
 * @param {Number} o.scale Scale factor for output sizing
 * @param {Function} o.callback Callback function with one param : canvas
 */
function htmlToData(o) {
  if (o.selector instanceof Node) {
    el = o.selector;
  } else {
    el = document.querySelector(o.selector);
  }

  function buildSvgImageUrl(svg) {
    b64 = window.btoa(svg);
    return "data:image/svg+xml;base64," + b64;
  }

  function getCss() {
    res = []
    styles = document.styleSheets;
    for (var i = 0; i < styles.length; i++) {
      var s = styles[i].cssRules;
      for (var j = 0; j < s.length; j++) {
        var r = s[j];
        res.push(r.cssText)
      }
    }
    return (res);
  }

  function setImage(url, callback) {
    var image = new Image();
    image.onload = function() {
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext("2d");
      var rect = el.getBoundingClientRect();

      canvas.width = rect.width * o.scale;
      canvas.height = rect.height * o.scale;
      ctx.scale(o.scale, o.scale);
      ctx.drawImage(this, 0, 0);
      callback(canvas);
    };

    image.src = url;
  }

  var data =
    "<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'>" +
    "<defs>" +
    "<style type='text/css'>" +
    getCss() +
    "</style>" +
    "</defs>" +
    "<foreignObject width='100%' height='100%'>" +
    "<div xmlns='http://www.w3.org/1999/xhtml'>" +
    el.innerHTML +
    "</div>" +
    "</foreignObject>" +
    "</svg>";

  url = buildSvgImageUrl(data);
  
  setImage(url, o.callback)

}