Fabric.js loadSVGFromUrl not displaying multiple imported SVGS

烂漫一生 提交于 2019-12-04 21:32:13

I think this was a bug that has been fixed in the library. Current fabricjs.com offer a kitchensink demo where you can try code.

http://fabricjs.com/kitchensink/

copy paste the code below in the execute tab to load 3 svg togheter without any strange issue or taking any precaution.

// clear canvas
canvas.clear();

// remove currently selected object
canvas.remove(canvas.getActiveObject());

fabric.loadSVGFromURL('../assets/1.svg', function(objects, options) { 
    var dollars = fabric.util.groupSVGElements(objects, options);
    canvas.add(dollars); 
    canvas.calcOffset();
    canvas.renderAll();
}); 
fabric.loadSVGFromURL('../assets/2.svg', function(objects, options) { 
    var drink = fabric.util.groupSVGElements(objects, options);
    canvas.add(drink); 
    canvas.calcOffset();
    canvas.renderAll();
});
fabric.loadSVGFromURL('../assets/3.svg', function(objects, options) { 
    var drink = fabric.util.groupSVGElements(objects, options);

    canvas.add(drink); 
    canvas.calcOffset();
    canvas.renderAll();
}); 

I actually do this as well, where a user can select any number of SVG files to load and later come back to edit their work. When they come back, I had the same issue while trying to reload the multiple files. In my case, I am actually building an array of objects that hold the svg url along with other useful pieces of information. This allowed me to load them into a stack (most suiting for my loading order, though you could easily implement it with a queue) and then pop them off one at a time.

var loadingLayerStack = [url1, url2, url3];

function ProcessLayerLoading()
{
    var layerUrl = loadingLayerStack.pop();
    DrawSvgToCanvas(layerUrl);
}

function DrawSvgToCanvas(url)
{
    fabric.loadSVGFromURL(url, function(objects, options) {
        var obj = fabric.util.groupSVGElements(objects, options);


        // ...any code for special handling of the loaded object


        // put object on the canvas
        canvas.add(obj);

        // get the next image
        ProcessLayerLoading();
    });
}

It is noteworthy to point out that I have the setting to enable Rendering when an object is added. So that canvas.add call also takes care of the initial rendering for me.

Hope this helps you somehow. :)

I just ran into this same problem, after seeing your post I decided to dig in to it a bit further myself. It turns out to be due to a scope issue in the onComplete callback within loadSVGFromURL. The problem stems from not isolating the url to a single scope; making multiple back-to-back calls results in the last url always being used when onComplete fires. As a workaround you could either chain your SVG loads or just make an ajax request yourself and load it using loadSVGFromString instead.

I'm learning fabric seems to be full of these bugs, errr, gotchas :(

Edit

I spoke too soon, loadSVGFromString suffers from the same weakness, it does not work asynchronously. That being said chaining is the most obvious work-around.

fabric.loadSVGFromURL() fetches the SVG via XmlHttpRequest. If you wait for each request to complete you can load multiple. Which means you need a tool for making and composing asynchronous promises in JavaScript. Check out q. https://github.com/kriskowal/q

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!