How do I Snap.load a SVG file and use it multiple times in the same Snap canvas?

1,197 views
Skip to first unread message

Brynjar Harðarson

unread,
Oct 2, 2014, 4:18:41 PM10/2/14
to sna...@googlegroups.com
I'm loading a couple of SVG images and everything works except for one of those SVG files because I need to use it 3 times, the second time I try to use it I get this error:

TypeError: image.select(...) is null

So image.select("path") stops working after I've used this path once.

    function other(x, y, active, style) {
       
var image = externalData["other"];
       
var shape = image.select("path").attr(style);
        shape
.attr({"opacity": active});
       
if (style.opacity != undefined) {
            shape
.attr({"opacity": style.opacity});
       
}
       
var scale = 0.9;
       
var w = shape.getBBox().width*scale;
       
var h = shape.getBBox().height*scale;
       
var x = x-w/2;
       
var y = y-(86*scale)/2;
       
var m = new Snap.Matrix();
        m
.translate(x, y);
        m
.scale(scale, scale);
        shape
.transform(m);
       
return shape
   
}

How can I make image.select("path") work every time and when it's done have the path visible in 3 places on the canvas?

Also, I need to load the all the SVG files before I execute the rest of the Snap code.

One solution might be to load the SVG three individual times and have externalData["other1"], externalData["other2"], externalData["other3"]. But I'd like my "other" function to access the path through a single interface (externalData["other"]), and even though right now I only have to use it 3 times I might in the future need to use it 4 times or 16 times, etc.

So how can I create a "new instance" of the Snap load data on each use of its path so it works every time?

I'm using Snap.svg 0.3.0

Snap load code:

var i = 0;
var data = ["/dep/svg/ruach.svg",
           
"/dep/svg/jechidah.svg",
           
"/dep/svg/other.svg"];

function loadImage(link) {
   
Snap.load(link, function(image) {
       
var linkSplit = link.split("/");
       
var filename = linkSplit[linkSplit.length-1];
       
var label = filename.split(".")[0];
        externalData
[label] = image;
        i
+= 1;
       
if (i == data.length) tree("#flower");
   
});
}

for (link in data) {
    loadImage
(data[link]);
}



Ian

unread,
Oct 2, 2014, 6:34:09 PM10/2/14
to sna...@googlegroups.com
It would be helpful to put a testing example on a fiddle, otherwise its difficult to see what actually works and what doesn't. I can't even see where you are appending the loaded fragment.

Quick few thoughts..a lot depends on what you need to do with the svgs after. If you need to manipulate them a lot, you can always element.clone() them. Otherwise you could look at something like the toDefs() and 'use' method or something to cut down on some bits, but I don't think thats what you are after. Its difficult without knowing more information and knowing how big the svgs are etc. If they are small, I would probably just clone them.

Thorsten Reitz

unread,
Oct 5, 2014, 10:32:59 AM10/5/14
to sna...@googlegroups.com
As written by Ian, you will need to clone the original path and use different IDs for each of the cloned paths. The ID can be set using
shape.attr { id: "new_ID" }

I did something similar - I load an SVG fragment and hide it...:

Snap.load("foreignElement.svg", function (loadedFragment) {
       
var foreignElement = loadedFragment.select("#TypeNameGroup");
        foreignElement
.attr({
           
"display": "none"
       
});
        paper
.append(foreignElement);

.. and later re-use it:

var typeNameGroup = document.getElementById("TypeNameGroup").cloneNode(true);
prefixIDs
(typeNameGroup, drawID + "_");
paper
.append(typeNameGroup);

However, I currently can't get the input inside the loaded foreignElement to work. It did work until a few months ago but now it stopped :(...

All the best,

Thorsten

Ian

unread,
Oct 5, 2014, 12:43:09 PM10/5/14
to sna...@googlegroups.com
Do you have an example on a jsfiddle at all Thorsten, I'm not quite sure what the input bit is that you mean ?
Reply all
Reply to author
Forward
0 new messages