toboR_rM toboR_rM - 3 months ago 11
Javascript Question

Re-appended Canvas element keeps content

Parser is a modul that is able to draw xml on the target canvas. After removing the original canvas element and appending the clean canvas, the canvas resets, but after further re-appendings the content of the canvas remains the same.



function setAttributes(elem, attrs) {
for (var key in attrs) {
elem.setAttribute(key, attrs[key]);
}
}

var Parser = (function() {
var cleanCanvas = (function() {
var canvas = document.createElement("canvas");
setAttributes(canvas, {
"id": "canvas",
"style": "border: 2px solid black",
"width": "200px",
"height": "200px"
});
return canvas;
})();

return {
parseSVG: function(data, target) {
lastTarget = $("#" + target).clone();
var canvas = document.getElementById(target);
var ctx = canvas.getContext('2d');

var DOMURL = window.URL || window.webkitURL || window;

var img = new Image();
var svg = new Blob([data], {
type: 'image/svg+xml;charset=utf-8'
});
var url = DOMURL.createObjectURL(svg);

img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
}

img.src = url;
var ctx = canvas.getContext('2d');
var DOMURL = window.URL || window.webkitURL || window;

var img = new Image();
var svg = new Blob([data], {
type: 'image/svg+xml;charset=utf-8'
});
var url = DOMURL.createObjectURL(svg);

img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
}

img.src = url;
},

clearCanvas: function() {
document.body.removeChild(document.getElementById("canvas"));
document.body.appendChild(cleanCanvas);
}
}
})();

//Tried in console:

var data =
'<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
'<foreignObject width="100%" height="100%">' +
'<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
'<h1>blah</h1>' +
'</div>' +
'</foreignObject>' +
'</svg>';

//Works properly
Parser.parseSVG(data, "canvas");
Parser.clearCanvas();

//Doesn't work properly
Parser.parseSVG(data, "canvas");
Parser.clearCanvas();

<!DOCTYPE html>
<html>

<head>
</head>

<body>
<canvas id="canvas" style="border: 2px solid black" width="200px" height="200px">
</canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="html2img.js"></script>
</body>

</html>





Why the content stays the same?

Answer

cleanCanvas is the same reference in everywhere, with same context. This means:

// after appending cleanCanvas to body

alert(cleanCanvas === document.getElementById('canvas'));

/* --> true */

You could make cleanCanvas a function instead, so you can re-generate it by calling it.

var getCleanCanvas = function() {
    var canvas = document.createElement("canvas");

    canvas.id = 'canvas';
    canvas.style.border = '2px solid black';

    setAttributes(canvas, {
        "width": "200px",
        "height": "200px"
    });

    return canvas;
};

Now:

document.body.appendChild(getCleanCanvas());