Trying to access SVG elements generated with <use> with JavaScript - javascript

I'm trying to use JavaScript (velocity.js) to animate an SVG that I've defined using <defs> and then instantiated with <use> and I'm having trouble accessing the DOM element of the SVG component I'm trying to modify. My code works with normal inline SVG just fine, but when I switch to the <defs>/<use> method it breaks.
When I use the inline SVG I can console.log the element in question and it returns information, but trying to access that same element generated with <use> returns an empty object. Is there anything in particular I need to be doing when trying to access the DOM elements of SVG generated with <use>?
The HTML
<div class="screen">
<svg>
<use href="/media/defs.svg#poppyIdle"></use>
</svg>
</div>
and top of defs.svg (generated by inkscape, all I did was add <defs> and <symbol>) (don't want to post the whole thing)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
<defs>
<symbol id="poppyIdle" viewBox="0 0 140 250">
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer12"
inkscape:label="eyelids"
style="display:inline"
transform="translate(-6.125676,0.02323548)">
<rect
style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.0694716"
id="rect942-3"
width="28.423023"
height="2.0695279"
x="34.666679"
y="34.632057" />
<rect
style="display:inline;fill:#4d4d4d;fill-opacity:1;stroke-width:0.0694716"
id="rect942-3-6"
width="28.423023"
height="2.0695279"
x="85.931053"
y="34.629658" />
</g>
</symbol>
</defs>
</svg>

SVG use elements are like shadow DOM elements in HTML. Only the attributes of the USE element itself is exposed via the SVG DOM - you cannot alter any properties on a single USE element instance that are being cloned from the original symbol. It's not like a macro.

Related

SVG get parent of an <image> referenced by <use>

I have an <svg> element which contains some <image> elements under <defs> tag, which are referenced by some <use> elements, like this:
<svg xmlns="http://www.w3.org/2000/svg" ...>
<defs>
<image height="100%" id="test" width="100%" xlink:href="data:image/png;base64,..."/>
</defs>
<g transform="translate(111,222)">
<svg height="100" width="200" x="0" y="0">
<use xlink:href="#test"/>
</svg>
</g>
</svg>
I have a javascript function which iterates through the svg element, and at a certain point I get the image which is referenced by <use>.
What I want to do is to get the height/width of the <svg> above <use> from the <image> element.
If a try:
image.parentElement
I get the <defs> element, not the <use> element.
How can I find the element which referenced the image?
I can try to search the element which contains xlink:href="#test" , but is there a direct way to get this from the referenced <image> ?
Sorry for the noob question, but I'm new to javascript/html.
No. There is not a way to get the <use> element directly from the <image> element.

Is there a way to register an onclick event handler on elements within an SVG image?

I'd like to load an SVG image within a HTML5 page and make it's components clickable. If the user moves the mouse over the shapes presented by the SVG an onclick event should perform some action. The goal is to enable the user to either click on parts of the SVG image or to click on data rows provided in a table below that SVG.
All SVG components are g elements that have a text element which in turn has text content that could be used as an ID for later on distinguishing the individual components.
SVG-Example (abbreviated by having only a single g-component and the text "abc"):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="232pt" height="260pt" viewBox="0.00 0.00 231.69 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g class="node">
<ellipse fill="#008000" stroke="#ffffff" cx="61.545" cy="-90" rx="46.2923" ry="18"/>
<text text-anchor="middle" x="61.545" y="-86.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">abc</text>
</g>
</svg>
Is there a way to use JQuery (or some other JavaScript library or pure JavaScript code) to register onclick event handlers on these g elements? And if so how can you do it?
I just added an ID to the g element, and with simple jQuery I could manage to get the onClick event.
<svg width="232pt" height="260pt" viewBox="0.00 0.00 231.69 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g class="node" id="myId">
<ellipse fill="#008000" stroke="#ffffff" cx="61.545" cy="-90" rx="46.2923" ry="18"/>
<text text-anchor="middle" x="61.545" y="-86.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">abc</text>
</g>
</svg>
$("#myId").on("click", function() { ... });
You can use whatever you want.
JSFiddle: http://jsfiddle.net/oc6zm1by/

Changing the SVG attributes with javascript

So trying to get my head around how to change a SVG using javascript (I tried d3js library. And I have some issues because I am not sure wether to use it or not).
I have created a simple icon (a star and a circle, to have something).
As far as I understand, what I need to do is to change the attributes of the <g> tag.
The icon have three id's, start circle(should be the whole picture), star (which is the star) and circle
Here is the SVG image.
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120"
height="120"
viewBox="0 0 120 120"
id="starcircle"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="starcircle.svg">
<defs
id="defstarcircle-def" />
<sodipodi:namedview
id="starcircle"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.32"
inkscape:cx="53.146552"
inkscape:cy="47.894737"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1440"
inkscape:window-height="821"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata5539">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="scLayer"
transform="translate(0,-932.36216)">
<path
sodipodi:type="star"
style="opacity:0.5;fill:#00aeef;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
id="star"
sodipodi:sides="5"
sodipodi:cx="59.05172"
sodipodi:cy="992.44832"
sodipodi:r1="49.260658"
sodipodi:r2="24.630329"
sodipodi:arg1="-0.27469391"
sodipodi:arg2="0.35362463"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 106.46551,979.08623 -24.307496,21.89157 4.253455,32.4346 -28.331542,-16.3529 -29.532743,14.0681 6.79764,-31.99826 -22.505694,-23.74002 32.532715,-3.42306 15.623459,-28.74026 13.308684,29.88267 z"
inkscape:transform-center-x="-0.60060082"
inkscape:transform-center-y="-4.1291064" />
<ellipse
style="opacity:0.5;fill:#0d00ef;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
id="circle"
cx="58.620693"
cy="991.80182"
rx="16.379311"
ry="16.594828" />
</g>
</svg>
So lets say that I want to rotate the star, for now only rotate it 180 degrees.
I would need to get the SVG image, then the shape, then append something like
rotate(180 , 50 , 50)
I tried doing it using d3, because it seemed like you needed a library to do it, but nothing I do seem to change the actual document. So what is the easiest way.
I created a jsfiddle with this example, and my attempt to do the rotate, but so far no luck.
I also hid the circle, mostly just to prove that the code is at least finding the objects, even if the hide function is a css option, and I want to do it using SVG transform
https://jsfiddle.net/qyt5o0s7/
Your javascript code was appending a <g> element to the #star element and then rotating the #star element. Remove the append() function and your code will then rotate the #star element. If you want to rotate the #star element around its center then you will also have add tranlate operation before and after the rotate operation. For example, change...
vard3star = d3.select("#star").append("g")
.attr("transform","rotate("+10 + "," + 15 +","+ 15 +")");
to...
var d3star = d3.select("#star").attr("transform","translate(60,992) rotate(10,15,15) translate(-60,-992)");
Also note that you were missing a space between var and d3star which was resulting in a global variable called vard3star.
Well your approach in the fiddle is wrong, Since you are not sure what the library to use or how to use it I like to give you the steps.
Use d3.js, It's great.
You just have to add a <g>, then create the star inside the <g>.
Give the <g> and id of something like starGroup
<g id="starGroup"></g>
then you can use d3 to translate the group.
d3.select('#starGroup')
.style(...);

jQuery add attribute to SVG string

Using jQuery I'm trying to add an ID attribute to the 'path' element of the following text template. The text is loaded with RequireJS and is referenced with a variable name (say mySvg).
The intention, is to have a loop based on the number of buttons required, and give each 'path' element (near bottom of markup) a unique ID, after which the text gets appended to a DOM element.
I'd be massively grateful if anyone can show me how (using jQuery) to add the ID attribute and value when the markup is in it's raw text format (ie before it's been added to the DOM).
Many thanks in advance...
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="141px" height="58px" viewBox="0 0 141 58" enable-background="new 0 0 141 58" xml:space="preserve">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="70" y1="62.5" x2="70" y2="-72.5">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.5667" style="stop-color:#3FA9F5"/>
</linearGradient>
<path class="svg button" fill="url(#SVGID_1_)" stroke="#000000" stroke-miterlimit="20" d="M137.5,43.5c0,6.627-5.373,12-12,12h-111
c-6.627,0-12-5.373-12-12v-30c0-6.627,5.373-12,12-12h111c6.627,0,12,5.373,12,12V43.5z"/>
</svg>
You can use JQuery to operate on fragments before they are appended to the DOM like this.
var e = $(yoursvg);
e.find("path").attr("id", "abcd");
// and then for example add it later
e.appendTo($('body'));
Demo here

SVG Inkscape generated file does not show flowRoot objects on browser

I´m dealing with SVG file in order to make some realtime animations on browser using AJAX.
Everything is fine except to make the browser (Chrome or IE9) to show the SVG image. The following HTML file does not show the flowRoot Text:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448"
height="600"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="lcl22.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="175.99454"
inkscape:cy="282.7269"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1366"
inkscape:window-height="706"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-452.36215)">
<path
sodipodi:type="arc"
style="fill:#008000;fill-opacity:1;stroke:#495677;stroke-width:23.16900063;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="circle1"
sodipodi:cx="227.14285"
sodipodi:cy="156.6479"
sodipodi:rx="47.142857"
sodipodi:ry="44.285713"
d="m 274.28571,156.6479 c 0,24.45833 -21.10658,44.28572 -47.14286,44.28572 C 201.10657,200.93362 180,181.10623 180,156.6479 c 0,-24.45832 21.10657,-44.28571 47.14285,-44.28571 26.03628,0 47.14286,19.82739 47.14286,44.28571 z"
inkscape:label="#path2985"
transform="translate(12.857143,635.71428)" />
<rect
style="fill:#00ff00;fill-opacity:1;stroke:#495677;stroke-width:4.86899996;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="box1"
width="284.28571"
height="110"
x="312.85715"
y="738.07648"
inkscape:label="#box1" />
<flowRoot
xml:space="preserve"
id="flowRoot3058"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;text-anchor:middle;text-align:center"
transform="translate(0,452.36215)"><flowRegion
id="flowRegion3060"><rect
id="rect3062"
width="365.71429"
height="100"
x="221.42857"
y="145.71428"
style="text-anchor:middle;text-align:center" /></flowRegion><flowPara
id="flowPara3064"
style="font-weight:bold;-inkscape-font-specification:Sans Bold">LCL22 TEST</flowPara></flowRoot> </g>
</svg>
I´ve tried to change the code to version 1.2 by changing the following line, but did not solve the problem...
version="1.2"
I need a easy way to edit and bring custom vector graphics to browser. I thought SVG would be a piece of cake, but I´m running aroud these kind of problems...
Any help appreciated.
Rds
The SVG 1.2 Full specification was never completed (as you can see from the link it's still in draft from 2005) and only Inkscape ever supported flowRoot I think. I don't think it's intended that flowRoot will be part of SVG 2 either as that is likely to implement flowing text with a different and more CSS compatible mechanism so flowRoot is best avoided.
Use the Convert to text" command in the Text menu to convert it to SVG 1.1 compliant text.
As others have said, you can use convert to text or unflow to remove the flowRoot.
Keep in mind however that the text will no longer stay within the boundary you specified.
To avoid flowRoot going forward, just click with the text tool and start typing rather that first dragging to set a bound for it.
To creat text that fits within a bounding box, I'm not sure what the best method is.

Categories