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)
}