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.
Related
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.
Main Question:
Is there a way to set a static width and height on <g> elements so that they don't get effected by transform attribute done on its parent view-box <svg> element?
i.e.
<svg id="viewbox" transform="translate(1,5)scale(2)">
// continuously gets the transform attr via js upon zoom event
<g>
<path "the shape of a triangle"/>
<path same/>
<path same/>
<path same/>
<path same/>
</g>
</svg>
I want everything under the <g> element to translate according to the zoom event transform values that the <svg> view-box receives, but not scale the dimensions of the <g> element. So that it looks like the screen is zooming into one section of the view-box, but without the <g> elements changing dimensions.
Instead of applying transformations to the svg element tag (svg) directly, you can use a group tag (g) to translate everything and a rectangle tag (rect) to scale only your 'viewbox'.
<svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(1, 5)">
<rect
id="viewbox"
fill="black"
width="100"
height="100"
transform="scale(2)" />
<!-- your elements down here -->
<rect
fill="grey"
width="20"
height="20"
x="10"
y="10" />
</g>
</svg>
Hope this help :)
I have created an SVG image which I am using within our website.
The SVG is displayed by inserting the XML into the HTML file, however, when loaded like this the SVG displayed differently compared with being displayed within an img tag.
<img src="http://elbrus.ecommercesuite.co.uk/Customisation Tool/SVG Templates/Bookmark.svg" />
I am just trying to reduce the line height within the following SVG:
https://jsfiddle.net/fahc2vvq/
I have to load in the XML version to edit the SVG within the website, Any ideas?
If you want a <foreignObject> to function correctly, you need to include a <body> element.
Note: I've removed the image from this demo to make it smaller.
<img src="http://elbrus.ecommercesuite.co.uk/Customisation Tool/SVG Templates/Bookmark.svg" />
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="73mm"
height="150mm"
viewBox="0 0 73 150"
version="1.1"
id="svg4523">
<g
id="layer1"
transform="translate(0,-147)">
<foreignObject
x="15"
y="150"
width="40"
height="60">
<body>
<p id="credit-card-text" style="font-size: 4px;text-align:center;text-anchor:middle;fill-opacity:1;font-weight:bold;line-height: 1;">Customise with your own message here.</p>
</body>
</foreignObject>
</g>
</svg>
I have an svg rect like this:
<svg class="legend-square">
<defs>
<pattern id="pattern1" width="3"
height="3" patternunits="userSpaceOnUse" patterntransform="rotate(-45)">
<rect width="2" height="3" transform="translate(0,0)" fill="purple"></rect>
</pattern>
</defs>
<rect width="12" height="12" fill="url(#pattern1)"></rect>
</svg>
When I inspect the second rect with Chrome it has no width and height. There are no CSS rules applying to it. Why doesn't it get affected by width and height?
One of the reasons why SVG file is rendered on front-end with zero height and width is missing <svg> tag attributes "height" and "width".
Incorrect:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 49 30">
Correct:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 49 30" width="49" height="30">
It works fine.
If the snippet works individually but size of div containing it in you code appears 0x0 then look into : Why is my div's height zero
Its usually caused when float is set.
<div>
<svg class="legend-square">
<defs>
<pattern id="pattern1" width="3" height="3" patternunits="userSpaceOnUse" patterntransform="rotate(-45)">
<rect width="2" height="3" transform="translate(0,0)" fill="purple"></rect>
</pattern>
</defs>
<rect width="12" height="12" fill="url(#pattern1)"></rect>
</svg>
</div>
You really haven't provided enough information. For instance, what is the parent element of your SVG?
Just because your <rect> has a width and hight, it doesn't mean your SVG does. SVG is not like HTML, where elements expand to fit their children. SVG is like the <canvas> element. You have to make sure it either explicitly (or implicitly) has a size.
You have not specified width or height attributes for your <svg> element, so they are both defaulting to "100%". What they are 100% of depends on what size the SVG's parent element is. Hence my first question above.
For an 'inline' SVG element you have to apply the styles, inside the svg element itself.
inside the <defs></defs> tags. Since it has its Own DOM[Document Object Model], Css Apllied to it from Outside, will have no effect.
You have Several different options for embeding an SVG, You can use it inline as in your example where you declare the <svg></svg> inside of your html/php document or you can use one of the many other methods listed below;
embed an: ..............................................<img src="../pathtoyourSvg"></img>
embed as an img with a fallback option: <img src="logo.png" srcset="logo.svg" alt="My logo">
use an: ....................................................<object type="image/svg+xml" data="image.svg">
<!-- Your fall back here -->
<img src="image.svg" />
</object>
use: .........................................................<embed type="image/svg+xml" src="image.svg" />
use an: ....................................................<iframe></iframe>
embed the Svg inside of a canvas element using Javascript:
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "path2your.svg";
You may Also Embed the Svg using Css Background image,
ie:
.mySvgContainer{
background-image:url('PathToMySvg');
}
But from the comments & Questions I have read, this need to be either Url or Base64 encoded, which seems a bit Hacky and not very convenient.
each of them have their own advantages and disadvantages.
Because of security reasons, some SVG embedding methods will block access to external resources including CSS, fonts and javascript. Especially when we have multiple images, ideally our embedding method should be able to refer to a single CSS, font or javascript file (to save resources) and be able to manipulate our embedded SVG.
Also worth mentioning that if you have display:flex; attached to an elemnet or its parent then the width and height values will have no effect on the flex items. So It may appear as 0, 0, in the console.
Some Useful Information & related questions:
Svg Coords & Units w3.org
Svg Width - Height
Applying Styles to an embedded Svg
You can wrap your svg element inside the html5 object element.
<style type="text/css">
object{
width:300px;
height:200px;
}
object svg{
width:100%;
height:100%;
}
</style>
<object>
<svg class="legend-square">
<defs>
<pattern id="pattern1" width="3"
height="3" patternunits="userSpaceOnUse" patterntransform="rotate(-45)">
<rect width="2" height="3" transform="translate(0,0)" fill="purple"></rect>
</pattern>
</defs>
<rect width="12" height="12" fill="url(#pattern1)"></rect>
</svg>
</object>
You can set height and width on the object element just link any other html element while you can set height width to 100% for SVG element. It will work. But first, test your SVG by opening the file directly in chrome.
I couldn't find the way how to embed two SVGs into SVG document. I need to do it with ability of code which would manipulate with both child SVG-s, and would like to have independent coordinates on both of those areas.
I don't like to do it in HTML, because I consider it too limiting comparing to SVG.
Many thanks!
An SVG document fragment consists of any number of SVG elements contained within an ‘svg’ element.
Source: http://www.w3.org/TR/SVG/struct.html#NewDocument
Basically:
<svg …>
<svg id="a" …>…</svg>
<svg id="b" …>…</svg>
</svg>
<svg>
...
<image x="..." y="..." width="..." height="..." xlink:href="path/to/your/file.svg" ></image>
...
</svg>
One of solution is '[parent svg] - [g] - [child svg]' structure.
<svg>
<g transform="translate(-,-)">
<svg>
...
</svg>
</g>
</svg>
You can set the cordinate of child svg as transform(translate) of g element.
demo:
http://hitokun-s.github.io/old/demo/path-between-two-svg.html