Render svg to canvas with images

2019-08-29 23:26发布

I am rendering an svg to a canvas (to save as png later).

    var svg = document.getElementById("mysvg");
    var svgData = new XMLSerializer().serializeToString( svg );  
    var canvas = <any>document.getElementById("canvas");
    var ctx = canvas.getContext( "2d" );

    var img = document.createElement( "img" );
    img.setAttribute( "src", "data:image/svg+xml;base64," + btoa( svgData ) );

    img.onload = function() {
        ctx.drawImage( img, 0, 0 );
        console.log( canvas.toDataURL( "image/png" ) );
    };

It works with base64 encoded images:

<image   x="10" y="10"  xlink:href="data:image/jpeg;base64, ...

But when using an url as xlink:href value it does not render the image to the canvas:

<image   x="10" y="10"  xlink:href="assets/myimage.png" />

1条回答
Bombasti
2楼-- · 2019-08-30 00:05

(edit:) Turns out it's by design (here's some details for Gecko, but it seems that other engines made the same choice, even though specs only forbid scripts - https://developer.mozilla.org/en-US/docs/Web/SVG/SVG_as_an_Image)

(the original answer:) It's possible that you have the problem of the tainted canvas.

Browsers have very strong policy of encapsulating data so that no origin (i.e. document from one domain) can access any sort of data from another origin, unless explicitly allowed by CORS headers. They can make requests to other domains, but they can never read back the results. This is a very strong rule and it underlies all the web security as we know it.

An interesting consequence is that if a canvas (or a canvas-like entity, like video) contains a picture that comes from another domain (protocol / port), it is marked as "tainted" and cannot be read back. This "tainted" status is carried over from canvas to canvas, so if you copy something from a tainted canvas into a pure one, the pure one gets tainted as well.

What you try to do should work if the document is served from the same protocol/domain/port as the svg picture.

查看更多
登录 后发表回答