Introduction
![]() |
| "Ghost" canvas for medium hall |
![]() |
| Simple example |
Once I have a copy hall scheme on invisible layer I can find a chair what user clicked by picking color of the invisible chair on mouse hover (don't confuse it with JS onmouseover event). But here is waiting for us a little surprise. I can draw SVG on canvas, but I can't call such methods: context.getImageData and canvas.toDataUrl! What's the matter?
Problem
Look the code below:<canvas></canvas>
<script>
var canvas = document.getElementsByTagName('canvas')[0],
ctx = canvas.getContext('2d'),
img = new Image();
img.onload = function() {
ctx.drawImage(img, x, y, w, h);
console.log(ctx.getImageData(x, y, w, h));
}
img.src = 'pathTo.svg';
</script>
ctx.drawImage(img, x, y, w, h);
console.log(ctx.getImageData(x, y, w, h));
}
img.src = 'pathTo.svg';
</script>
If you try to do something like this in Chrome, you will get an error: "Unable to get image data from canvas because the canvas has been tainted by cross-origin data". And then "Uncaught Error: SecurityError: DOM Exception 18". Run this snippet and and check it out. Open your developer tools panel and look at the console.
Why did this happened you may ask? I found the answer here and here.
The most important things in a few words:
There's nothing native that allows you to natively use SVG paths in canvas. You must convert yourself or use a library to do it for you.
If the source attribute of HTML img-element is set to "smth.svg", and this image element is rendered on Canvas element, the origin-clean is set to false even if same origin policy should be satisfied.
If the SVG is represented as a data URI: "data:image/svg+xml;base64,dVAx..." and this string is set as source attribute of a HTML image, which is then rendered on Canvas element, the origin-clean also sets to false.
SVG with Safe Elements. This testing becomes more interesting if we do the same tests with a SVG that uses only safe elements, such as <rect> and <circle>. Result will be that the Canvas origin-clean property sets permanently to false, even if all the elements can be considered as "safe" and same origin.Personally I, Patrick from Chromium issue discussions and Antony from Stackoverflow think, that problem is in SVG namespace declarations which is located at http://www.w3.org/, which is of a different origin.
Decision
If it is important for you to use exactly а SVG you may use external library canvg. Note the method drawSvg() which are expands a context object.ctx.drawSvg('pathTo.svg', x, y, w, h);
But I don't use this library, because this solution are too expensive for us.
I use SVG images to draw visible part and png image for ghost canvas generation. I don't use images on both part, because canvas has problem with anti-aliasing after image resize and special CSS styles do not help.
Epilogue
Hope this article save your time.


No comments:
Post a Comment