phantomjs throwing DOM exception 18 on canvas.toDa

2019-02-22 11:25发布

问题:

I'm trying to convert svg to png images using phantomjs:

var page = require('webpage').create();

page.evaluate(function() {

    var svg = '<svg class="tnt_tracks_svg" width="800" height="180" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/\
xlink"><rect width="10" height="10" fill="red"></rect></svg>';

    var src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svg)));

    var img = new Image();
    img.src = src;
    img.onload = function() {
        var canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;
        var context = canvas.getContext('2d');
        context.drawImage(img, 0, 0);
        var src = canvas.toDataURL(); // DOM Exception 18!
    }
});

But I'm getting a DOM Exception 18 when calling toDataURL. I have seen in other similar questions that this may happen if the svg is hosted in other domains etc..., but in my case I'm providing the svg src!. What is wrong with the code above? Why is it firing the DOM Exception?

A similar code looks good in jsfiddle (no phantomjs, tested in chrome and FF). And this phantom example is also working using fabric.js:

page.includeJs("http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js", function () {
    page.evaluate(function() {
        var svg_text = '<svg width="600" height="400"><g><rect width="10" height="10" fill="red"></rect></g></svg>';

        fabric.loadSVGFromString(svg_text, function (objects, options) {
            var loadedObject = fabric.util.groupSVGElements(objects, options);

            var canvas = new fabric.Canvas('canvas');
            canvas.add(loadedObject);
            canvas.calcOffset();
            canvas.renderAll();
            console.log (canvas.toDataURL('png'));
        });
    });
});

I'm trying to find the relevant code in fabric.js, but any help would be much appreciated.

回答1:

Ok, answering my question after some research...

It looks like webkit is always setting the origin-clean flag to false every time a data-uri string is set as source attribute of a HTML image, which is then rendered on Canvas element. Firefox and Chrome (for example), allow this for some cases, but not webkit.

Fabric.js doesn't suffer from this problem because it renders the shapes into canvas but don't use the data uri for that, so the canvas is not tainted.

Another solution is to use canvg and SVG.toDataURL.

References here:

Issue explained: http://svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back/#security_issues

Webkit issues: Several, see for example this and this