Live contentEditable foreignObject SVG to Canvas
by Isaiah Odhner
December 04, 2019
HTML
<svg width="100" height="150" id="test-svg" xmlns="http://www.w3.org/2000/svg" version="1.1">
<foreignObject x="0" y="0" width="100" height="150" >
<div xmlns="http://www.w3.org/1999/xhtml" contenteditable>
Here is a <strong>paragraph</strong> that requires <em>word wrap</em>.
This is <code>contentEditable</code>.
</div>
</foreignObject>
</svg>
CSS
svg,
canvas {
position: absolute;
top: 15px;
left: 15px;
transform: scale(3);
transform-origin: left top;
}
canvas {
pointer-events: none;
z-index: -1;
image-rendering: crisp-edges;
image-rendering: pixelated;
image-rendering: -moz-crisp-edges;
}
svg * {
color: transparent !important;
background: transparent !important;
caret-color: black;
}
JavaScript
var svg = document.getElementById("test-svg");
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
canvas.width = svg.clientWidth;
canvas.height = svg.clientHeight;
canvas.style.outline = "5px solid lightgray";
var last_svg_source;
setInterval(()=> {
var svg_source = new XMLSerializer().serializeToString(svg);
if (svg_source === last_svg_source) {
return;
}
var blob = new Blob([svg_source], {type: "image/svg+xml;charset=utf-8"});
var blob_url = URL.createObjectURL(blob);
var img = new Image();
img.onload = ()=> {
URL.revokeObjectURL(blob_url);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
canvas.style.outlineColor = "lime";
};
img.onerror = (e)=> {
URL.revokeObjectURL(blob_url);
canvas.style.outlineColor = "red";
console.log("failed to load image", e);
};
img.src = blob_url;
last_svg_source = svg_source;
}, 10);