Open hfmanson opened 6 months ago
One of the advantages of having to go through an <img>
element is that this allows for easier sandboxing of the SVG image. For instance here I modified the original fiddle to show both the in DOM <svg>
and the one drawn on the canvas. We wouldn't want the :visited
selector to be leaked in the canvas where it can be read back.
So this means that the browser can't go directly from the image rendered into the doc to the canvas, it will have to recompute it there, or to taint the canvas which puts quite a limit on the feature.
I'd personally propose that if we do this for <svg>
, why not do it for any element? IIRC there was already a proposal for such an "any element as source" idea, though I can't find it right now.
Indeed, CanvasRenderingContext2D.drawImage() does not render the image, but its bitmap which is a bit confusing (better name drawBitmap?). So passing a SVGSVGElement is not appropriate for drawImage(). bitmap only is demonstrating the above. When drawing the image on the canvas opacity is not applied, just the image bitmap is drawn.
I could change the proposal to "add CanvasRenderingContext2D.drawDocument() method", which has the same signature a drawImage apart for its first parameter which would be a document instead of an image-like parameter with a bitmap. The semantics can be the same as when a SVG image src
is supplied, which also converts a SVG to a bitmap.
I think having a drawImage with any element as parameter is not possible, e.g. it's not possible to draw a SVG circle without it's svg document. Is that correct?
@Kaiido makes a good point that it needs the same restrictions as <img>
SVG, so perhaps this isn't worth doing. Supporting arbitrary (styled) node trees without revealing anything about the end user is rather involved and not something anyone has been willing to take on thus far.
having read @Kaiido's comment I think the semantics of drawImage()
having a SVGSVGElement as parameter should be as if it would be rendered through an <img>
element.
There is an active proposal for converting any DOM content into a canvas image, and even more so render HTML content directly to the canvas. This is in early discussions pending discussions among browser vendors, though there is a prototype in Chromium (not fully functional). See the Explainer.
Incubation will happen at WICG.
What is the issue with the DOM Standard?
Currently a
SVGSVGElement
can only be rendered in a HTML canvas byaddEventListener("load", () => { function drawSVGSVGElement(svgsvgElement) { // serializing the containing document to a string const s = new XMLSerializer(); const str = s.serializeToString(svgsvgElement.ownerDocument); // creating a blob out of it
let blob = new Blob([str], {type: 'image/svg+xml'}); // convert the blob to an url let url = URL.createObjectURL(blob); // create an image element and assign the src property
let image = document.createElement('img'); image.src = url; // adding an EventListener which draws the loaded image.*/
image.addEventListener('load', function () { const canvas = document.getElementById('canvas'); const context = canvas.getContext("2d"); context.drawImage(image, 0, 0); URL.revokeObjectURL(url); }); } function getSVGSVGElement() { const parser = new DOMParser(); const doc = parser.parseFromString(svgSource, "image/svg+xml"); return doc.documentElement; } const svgsvgElement = getSVGSVGElement(); drawSVGSVGElement(svgsvgElement); }, false);