I have this model
<svg id=cardModel viewBox="0 0 100 200">
<rect x="0" y="0" width="100" height="200" fill="transparent" stroke="black"></rect>
<text id="text" x="25" y="125" font-size=100>change me</text>
</svg>
and I want to change the text from
<use href="#cardModel"></use>
I tryed using getElementById but as expected the <use> have no child.
Here's a jsFiddle: https://jsfiddle.net/e6gh07fa/316/
(seems like we can't use namespace in SO scripts)
I know I could use Node.cloneNode() but I want to know if there is another way
Related
I want to access the SVG code created by MathJax via javascript. Apparently, MathJax put the SVG <path> under shadow-root, which is not directly accessible by javascript. Here is a picture of the elements given by Chrome
If I get the <svg> element by any javascript method, the <path> children will not be included.
You cannot avoid shadow-root. It is not put there by MathJax renderer. It is because of the use tag.
From MDN:
The <use> element takes nodes from within the SVG document, and duplicates them somewhere else.
So MathJax creates svg pathes and gives them ids and reuses them. Say the letter a is rendered into svg, and MathJax stores it in the svg with an id and use it when the letter a is needed to be rendered.
Below example from MDN speaks better.
<svg width="80" height="80" xmlns="http://www.w3.org/2000/svg">
<style>
.classA {
fill: red;
}
</style>
<defs>
<g id="Port">
<circle style="fill: inherit;" r="10"/>
</g>
</defs>
<text y="15">black</text>
<use x="50" y="10" href="#Port" />
<text y="35">red</text>
<use x="50" y="30" href="#Port" class="classA"/>
<text y="55">blue</text>
<use x="50" y="50" href="#Port" style="fill: blue;"/>
</svg>
I try to make SVG text (wrapped in <text> of course) place on SVG <rect>.
And I want to make it look like text centered in my rect.
But strange thing I got there, it looks not like I assumed.
It looks like this
When I assumed it gonna be look like that
Whats wrong with that?
First I tought that equal x and y in <text> and <rect> will work, but it was like in picture below
I tought that y="50%" in text will force text to ancor somewhere in the middle. But I can achieve in only at y="80%" as you can see.
Original markup is here
<svg height="500" width="500" class="ng-scope">
<svg height="50" width="393.703125" y="0">
<g>
<rect x="0" y="0" height="50" width="393.703125" style="fill: #A8A8A8">
</rect>
<text font-family="Airal" font-size="45" x="0" y="50%" inline-size="200">
TEST TEXT IN SVG
</text>
</g>
</svg>
</svg>
The y property is per default applied to the text bottom line - so there is a difference between the y-position of a text and the y-position of lines, rectangles, or other shapes.
You can use the alignment-baseline property e.g. with middle to achieve better results. Here's the w3c description with many more options.
<svg height="500" width="500" class="ng-scope">
<svg height="50" width="393.703125" y="0">
<g>
<rect x="0" y="0" height="50" width="393.703125" style="fill: #A8A8A8">
</rect>
<text font-family="Airal" font-size="45" x="0" y="50%" inline-size="200" alignment-baseline="middle">
TEST TEXT IN SVG
</text>
</g>
</svg>
</svg>
add viewBox. Again i am not expert at svg , have done just some work but this may work.
<svg height="500" width="500" class="ng-scope">
<svg height="50" width="393.703125" y="0" viewBox="0 0 90 90">
<g>
<rect x="0" y="0" height="50" width="393.703125" style="fill: #A8A8A8" >
</rect>
<text font-family="Airal" font-size="45" x="0" y="50%" inline-size="200">
TEST TEXT IN SVG
</text>
</g>
</svg>
</svg>
Replace Circle Elements with Icons
I am trying to make my SVG circle elements look like shopping carts. Is there a way to completely replace the definition of a circle element in svg so that it renders a certain icon ?
I'd like
<circle cx="280px" cy="411px" r="4.976112128"></circle>
to look like
<i class="fa fa-shopping-cart"></i>
If not, is there a simpler way to display an icon whenever the circle element is called ?
Thank you very much !
You can try styling the <circle> element with CSS's background-image property:
circle {
background-image: url(http://www.example.com/bck.png);
}
You can define your own elements and call those instead of circles. This way you can still use circles if needed elsewhere.
If you are not looking to use CSS you can use "defs" and "use".
<?xml version="1.0" encoding="utf-8"?>
<!-- from this website http://tutorials.jenkov.com/svg/svg-and-css.html -->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<g id="shopcart">
<image x="499.5" y="242.4" height="40" width="40" id="cart" preserveAspectRatio="none" xlink:href="c:\temp\cart.png" opacity="1" style="pointer-events: none"/>
</g>
</defs>
<use xlink:href="#shopcart" x="10" y="50" transform="translate(150,50)" />
<use xlink:href="#shopcart" x="100" y="250" />
<use xlink:href="#shopcart" x="200" y="250" />
<use xlink:href="#shopcart" x="300" y="250" />
</svg>
The below selector will not find <clipPath> elements inside <defs> on Chrome (38):
d3.selectAll('defs clipPath')
(This is D3.js code but I suspect underlying querySelectorAll issue)
It works fine on Firefox. Is there a different selector syntax to use that will work on both browsers?
In the example below on Firefox you will see the whole text because the clip path is removed. But on Chrome it will be cut off after 85 pixels because the clip path is not removed.
d3.selectAll('defs clipPath').remove();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg height="200" width="400">
<defs>
<clipPath id="clip1">
<rect id='tt' x="0" y="0" width="85" height="15"></rect>
</clipPath>
</defs>
<text clip-path="url(#clip1)" x="0" y="15">This text should all be visible once we remove the clip-path</text>
</svg>
As Lars pointed out, this was a webkit bug, and now in Blink it still exists as Issue 237435: querySelectorAll unable to find SVG camelCase elements in HTML
So until it's fixed, using a class selector is probably the best workaround.
d3.selectAll('defs .clippy').remove();
d3.selectAll('defs .clippy').remove();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg height="200" width="400">
<defs>
<clipPath id="clip1" class='clippy'>
<rect id='tt' x="0" y="0" width="85" height="15"></rect>
</clipPath>
</defs>
<text clip-path="url(#clip1)" x="0" y="15">This text should all be visible once we remove the clip-path</text>
</svg>
As shown in this fiddle it's possible to render a CSS sprite in SVG using the foreignObject element.
However this isn't supported in IE, so I was wondering if there was another way to do it.
I suspect the answer may be no, because I found two unresolved questions on this (1,2)
I'm using d3.js so any answer that spells out the d3 way to do this would be a bonus.
You could pick out parts of an image using a clipPath if necessary. Extend your jsfiddle like this to see what I mean...
<div class='source youtube'></div>
<svg width="100%" height="100%">
<foreignObject height=50 width=50>
<div class='source facebook'></div>
</foreignObject>
<defs>
<clipPath id="c">
<rect y="10" width="7" height="10"/>
</clipPath>
<clipPath id="c2">
<rect x="7" y="12" width="7" height="10"/>
</clipPath>
</defs>
<image transform="scale(4.5)" y="-5" width="40" height="20" xlink:href="https://s3.amazonaws.com/856/sprite.png" clip-path="url(#c)"/>
<g transform="translate(-30, 0)">
<image transform="scale(4.5)" x="0" y="0" width="40" height="20" xlink:href="https://s3.amazonaws.com/856/sprite.png" clip-path="url(#c2)"/>
</g>
<svg>