Load SVG into a specific div with Snap SVG - javascript

What is the correct way to load an SVG file into a specific div using SnapSVG?
Following the documentation I have this JS:
var s = Snap();
Snap.load("fox.svg", function (f) {
s.append(f.select("g#fox"));
});
This loads the SVG just above the body tag, however if I try to set it's location, nothing happens, there is no error. This is what I have attempted so far:
var s = Snap('#myDiv');
Where am I going wrong?

This should work, its not far removed from your example, so its hard to tell whats wrong with yours without a live example and the svg to look at.
If you want to upload a fiddle or something, it may help.
var s = Snap("#svgdiv");
var l = Snap.load("path.svg", onSVGLoaded ) ;
function onSVGLoaded( data ){
s.append( data );
}
Edit: Just to extend on Duopixels answer, the element you are trying to add, should be an svg element (ie
<svg id="mysvgtoload">...</svg> // you can add an svg to a div
<g id="mygrouptoload">...</g> // you can't add this to a div, but could to an svg element
in the file) or add the element (g or path or whatever) to an existing svg tag/element in your html. I suspect you may be trying to add a element direct to a div, which won't work, but its hard to tell without the file.
Also double check that Snap is loaded fine, and you can do a console.log( data ) in the function to check that it has loaded the markup correct.

Related

When i add a JavaScript element to my SVG file it disapears

I am using snapsvg to manipulate my SVG file created with Inkscape.
When i try to add a rectangle from snapsvg to my already existing svg i get a blank page. You can see a example how i manipulate the svg.
I tried to make a new script section but it always but the rectangle or the element either above or under my svg. And i want it to be inside my svg.
//Run script right away
window.onload = function () {
var s = Snap("#iconDiv");
//Load SVG file
Snap.load("lager2.svg", function(f) {
//Load Rectangles and elements
Element1 = f.select("#Element1");
Group1 = f.select("#Group1");
//manipulate my rectangle
Group1.hover(function() {
Element1.attr({
fill: "red"
});
});
});
}
The only error message that i get is this one:
Uncaught TypeError: s.circle is not a function
at window.onload
Is the element #iconDiv a div, as the name suggests?
The getting started docs for Snap.svg says
First lets create our drawing surface out of existing SVG element
So you need to change your line of code accordingly:
var s = Snap("#iconDiv"); // Target a <div> won't work
to
var s = Snap("#iconSvg"); // Target the <svg> element instead

SVG <image> element created in JS does not display

I have an <svg> element (with viewBox set) and I append a programmatically constructed <image> element to it, like this:
const img=document.createElementNS('http://www.w3.org/2000/svg','image');
img.setAttribute('width','100');
img.setAttribute('height','100');
img.setAttribute('xlink:href','data:image/png;base64,iVBORw0KGgoAAA'+
'ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4'+
'//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU'+
'5ErkJggg==');
document.querySelector('svg').appendChild(img);
It is present in the SVG but nothing is displayed. However when I call img.outerHTML = img.outerHTML; to sort of recreate it from its text representation, it starts displaying properly.
Anyone could help me understand what's going on? How should I create the element in JS to make it display properly?
JSFiddle
For SVG-2 ready browsers you can simply do setAttribute("href", url).
However, in SVG-1.x you must use setAttributeNS('http://www.w3.org/1999/xlink', 'href', url);
Actually with setAttributeNS, you can also use 'xlink:href' for the second parameter or 'foo:href', since setAttributeNS takes care of mapping to the correct NameSpace and kind of discards what comes before :, but setAttribute doesn't and thus creates a kind of null:xlink:href attribute, which doesn't map to anything known by the browser and thus fails.
const url = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const img = document.createElementNS('http://www.w3.org/2000/svg','image');
img.setAttribute('width','100');
img.setAttribute('height','100');
img.setAttribute('href', url); // SVG-2
img.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', url); // SVG-1.x
document.querySelector('svg').appendChild(img);
<svg viewBox="0 0 100 100"></svg>

How can I access SVG elements in html (with CSS preferably) without pasting the code in directly?

I was trying to work through this tutorial as a practice for a bigger project I'm working on.
My actual SVG is really big, so I would rather not just copy paste the whole giant code directly into HTML.
But here's the practice one I made (i'm also not sure how to clean SVGs made in Inkscape, but I deleted some of the stuff that didn't seem necessary.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
id="svg1"
version="1.1"
viewBox="49.595489 30.040314 84.135223 84.305336"
height="84.305336mm"
width="84.135223mm">
<path class="path5076"
id="path5076"
d="m 70.303571,78.340773 c -4.032971,0.006 -8.033187,1.698025 -10.862132,4.572387 -2.828946,2.874362 -4.455685,6.891674 -4.445904,10.924637 0.0095,3.927963 1.572604,7.841853 4.315065,10.653953 2.74246,2.8121 6.641232,4.47709 10.569138,4.45364 4.633366,-0.0277 9.108311,-2.43049 12.384652,-5.70683 3.574526,-3.57453 6.411017,-6.242046 9.347584,-9.825986 0,0 7.17598,-6.918764 10.743336,-10.51178 3.56737,-3.593016 7.41006,-7.169152 11.08478,-10.843875 3.34645,-3.346446 6.32139,-6.581106 9.51049,-9.812482 3.3753,-3.420038 5.15813,-7.12199 5.18334,-11.661986 0.0216,-3.889398 -1.60848,-8.155743 -4.38434,-10.880165 -2.77587,-2.724421 -6.6563,-4.279784 -10.54572,-4.261811 -3.8759,0.01791 -7.72562,1.595418 -10.48769,4.314587 -2.762056,2.71917 -5.002206,6.149863 -4.776456,11.428746 -0.0484,4.514439 2.874106,9.098792 5.148056,11.372746 3.19237,3.192372 6.9848,6.227335 10.17717,9.419709 3.20164,3.201638 6.0452,5.990107 9.58187,9.526778 1.80732,1.807321 3.93629,5.149881 4.68721,7.593023 0.75092,2.443141 1.01197,5.054051 0.5999,7.576553 -0.55185,3.378163 -2.33545,6.072793 -4.93781,8.296363 -2.60235,2.22358 -5.80201,3.69214 -9.22483,3.7206 -4.69281,0.039 -9.04011,-1.51725 -12.0905,-4.81311 -3.187696,-3.44421 -7.211206,-7.037566 -10.268806,-10.463896 -3.057595,-3.42633 -6.28628,-6.607684 -9.408672,-9.762441 -3.174881,-3.207791 -7.386446,-5.316042 -11.899731,-5.30936 z"
style="fill:none;fill-opacity:1;stroke:#febc00;stroke-width:10.80000019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</svg>
In the tutorial it says:
Let's target the path with CSS (assuming we're using inline SVG here,
or via an 'object')
which is great because just uploading svg without copy-pasting is exactly what I wanted. But I'm not sure how to proceed now. From what I could find, the only way to access the inside parts of SVG is through javascript, which I've never done before as I don't know javascript.
So I have this
<object id="svg1" data="path.svg" type="image/svg+xml"></object>
Now I'm trying to figure out how to access the path inside the SVG.
I tried putting in this code that I found, but it didn't do anything.
<script>
window.onload=function() {
var a = document.getElementById("svg1");
var svgDoc = a.contentDocument;
var svgItem = svgDoc.getElementById("path5076");
svgItem.setAttribute("fill", "lime");
};
</script>
I then found someone saying that I had to let the SVG load first, so I added
<script>
var mySVG = document.getElementById("svg1");
var svgDoc;
mySVG.addEventListener("load",function() {
svgDoc = mySVG.contentDocument;
alert("SVG contentDocument Loaded!");
}, false);
</script>
but that also didn't seem to work.
This is my first stab at JS, so any help is appreciated.
But if you know how this can be done with CSS PLEASE let me know, I'm much more comfortable with it (as comfortable as I can be after two weeks of learning it, as opposed to 0 weeks with JS)
Edited as per suggestion, but I think I'm still doing it wrong.
Also, I only left "fill:none;fill-opacity:1;stroke:#febc00;stroke-width:10.80000019" in style and removed everything else. Does that mean I can still assign attributes like stroke-dasharray or do they have to be predefined inside style first?
still hoping someone has some other input
The style precedence, from lowest to highest, is
attributes
CSS style sheets
inline styles
Your SVG uses inline styles (style="fill:none;fill-opacity:1;...).
So your code is correct but no matter what you do with the "fill" attribute, it is overridden by the inline style, so svgItem.setAttribute("fill", "lime"); is useless.
You need to alter the inline style somehow.
The easiest solution is to change the inline style by calling:
svgItem.setAttribute("style", svgItem.getAttribute("style").replace("fill:none;","fill:lime;"))
but you can also remove the inline style completely and work with the attributes/external CSS instead.
another option is to convert inline style to attributes:
<script type="text/javascript">
window.onload=function() {
var a = document.getElementById("svg1");
var svgDoc = a.contentDocument;
var svgItem = svgDoc.getElementById("path5076");
// replace inline style with attributes
var styleText = svgItem.getAttribute("style");
svgItem.removeAttribute("style");
for (let pair of styleText.split(';')) {
let [key, value] = pair.split(':');
svgItem.setAttribute(key,value);
}
// now you are ready to work with the attributes
svgItem.setAttribute("fill", "lime");
};
</script>

Access current position in svg using javascript

I want to access current position that defined in variables. After that I want to make the element of that position was colored automatically when I load the page. The problem is I don't know how to access that defined position and append the color to html when its load.
I've try it in this, but it gets nothing colored when I load the page. Maybe my code was wrong and can anyone help?
https://jsfiddle.net/ax47kvu5/1/
var gigi = "P15";//id of g
var posisi = "C";//id of polygon
var kondisi = "amf";
if(kondisi=="amf"){
var group = $('polygon').parentNode().attr(gigi);
group.attr(posisi).css({fill: "#333333"});
$('polygon').html('XX');
}
https://jsfiddle.net/9n9jack8/ - In your example you didn't load jQuery, this is the first issue.$("#P15").find("#C").css({fill: "#333333"});

How to append an svg loaded by d3.xml into an svg

Trying to load external svgs in to a dynamically created svg but still access the properties of the loaded svgs. That is why I'm using d3.xml but haven't figured out how to integrate it in to the dynamic svg created with d3.
Code and js console here
The code produces this svg
<svg id = "svgObj">
<g class = "grp"></g>
<g class = "grp"></g>
</svg>
I'm trying to load circle.svg within each element so it looks like this
<svg id = "svgObj">
<g class = "grp"><svg id=minus>...</svg></g>
<g class = "grp"><svg id=minus>...</svg></g>
</svg>
I tried the code below but console errors that there is no appendChild method
var grps = d3.selectAll( "g" );
img = grps.appendChild( svgNode.cloneNode( true ) );
Thanks ahead
As #helderdarocha explained, you're mixing up your d3 methods with your plain Javascript methods. That answer gave you how to do it with plain Javascript methods, I'll balance that out by explaining how to do it with d3 methods.
To append a new element within each element of a d3 selection, the method name is simply append, not appendChild. The parameter to append is either a tag name (for which d3 creates a new element of that type for each element in the selection) or a function that returns an actual DOM element (the function will get called for each element in the selection with the data value and index as parameters). Since you're cloning an existing node, that's the version you want to use:
var grps = d3.selectAll( "g" );
img = grps.append( function(){return svgNode.cloneNode( true );} );
I haven't used D3 before but it seems easy to understand. The error message says that Array has no appendChild() method. I read the documentation and discovered that the selections return as double nodes (see Operating on selections) so you would have to add [0][0] (which would select the first node) to be able to use appendChild().
This selects the first node using plain DOM and produces no error (and draws a partial shape on the output):
var grps = d3.selectAll( "g" )[0][0];
Since you need to insert code in each node, you can use each() (see Control) like this:
d3.selectAll( "g" ).each(function() {
img = this.appendChild( svgNode.cloneNode( true ) );
});
I tested it on your code and it produces a black circle with a white dash in the middle. Is that what you expected?

Categories

Resources