This is the example https://codesandbox.io/s/4xwv953mv0
There are three lines. The original one is hidden the second linked to it by id xlink:href="#line", the third links the second the same way.
Move the slider, the lines will go up in the Chrome, and only one will go up in the Firefox.
If it is a Firefox bug what to do? Is there a way to update SVG with Vue?
Yes. This is a known Firefox bug. Firefox bug report here and here.
There is a simple fix here though. Just change your second use so that it points to the <line> directly, rather than at the <use>.
<use
id="Svg"
xlink:href="#line"
transform="translate(40,10)"
></use>
As an aside. I recommend that you put your line in a <defs> section, rather than hiding it with display:none. This is what <defs> is for, and using display:none can have unintended consequences in some cases.
<defs>
<line
id="line"
x1="0"
y1="0"
x2="100"
:y2="value"
vector-effect="non-scaling-stroke"
/>
</defs>
I'm using a big svg that contains flags of countries, eg
<symbol viewBox="0 0 640 480" id="flag-be">
<g fill-rule="evenodd" stroke-width="1pt">
<path d="M0 0h213.34v480H0z" />
<path fill="#ffd90c" d="M213.34 0h213.33v480H213.33z" />
<path fill="#f31830" d="M426.67 0h213.34v480H426.66z" />
</g>
</symbol>
It works great and I can simply svg use #flag-be and voila, got a my flag.
<svg class="icon flag-be"><use href="#flag-be"></use></svg>
However, I'd like to add a border around the flags (because some that have a lot of white looks strange without it), ideally something that can be set via css only
It works fine when I have each flag into separate svgs (using border), but I failed to make it work when I use several flags as part of a single svg containers (a graph)
What's the easiest? whould I add a a new element in each symbol for the border? What's the most flexible to style "used" symbols in a svg?
Neither <svg> nor <use> nor <g> elements are graphical elements. Trying to set a style altering the graphical appearance on them will only lead to the style being inherited by its children. So, if you set a stroke on <use>, it will be inherited by all the path elements, and you get a border around every flag field.
(A point to remember: Content cloned with a <use> element can inherit styles, but they cannot be targeted with CSS selectors.)
So why does setting a border work on the outermost <svg> element? Because that element is treated as part of the HTML namespace and rendered as if it was an ordinary <span>, while for its children in the SVG namespace the border property has no meaning.
In your use case, you need to add a graphical element surrounding the whole flag. Probably at the point of use, like this:
<svg ...>
...
<svg class="icon flag-be" width="24" height="16">
<use href="#flag-be" />
<rect width="100%" height="100%" style="fill:none;stroke:black;stroke-width:1" />
</svg>
...
</svg>
Note the inner <svg> element. Its purpose is to give a reference to the percentage width and height of the <rect>. Otherwise, they would be computed in relation to the outer <svg>.
Currently, width and height must be set as attributes on an inner <svg> element. SVG 2 defines them as presentation attributes that can be set with CSS, but some browsers still only allow that on outer <svg> elements.
I am making an animated SVG donut chart. My best try for the moment is here. But this is not exactly what i want. I want the elements appear at the start, then fade out before another one has appeared on the screen, then wait for all other elements to appear and fade out, and then to start this cycle again from the first element. As you see, now elements are fading in/out together, only their animation start times differ. I tried values/keyTimes attributes in another try. But the animation is not working in any browser i know.
Here is the problem code in first SVG:
<animate
attributeName="opacity"
begin="0ms" //This is for the first element, for anothers it differs
//I wish there is `pause` attribute, to pause animation repiting...
dur="3000ms"
from="0.7"
to="0"
repeatCount="indefinite"/>
Here is another code sample
<animate
attributeName="opacity"
begin="0ms"
keyTimes="0,0.2,1"
values="0.7,0,0"
dur="15000ms"
repeatCount="indefinite"/>
As you see, i tried to increase animation duration, but to end fading of element at 20% (i have five elements to fade) of this time. But it does not work.
Tried reordering attributes, using from and to with two-valued keyTimes and long dur with no effect. There must be some cunning trick here...
P.S. This is almost what i want, but i need animation to repeat.
The problem is commas in keyTimes and value attributes - need to use semicolons and read docs twice.
I'm looking for a solid answer on whether or not there is an equivalent to -webkit-mask in Gecko browsers/Firefox?
If not, is there any way of degrading -webkit-mask in CSS to a straight background-image deal or should I just give up and use Javascript?
Thanks a lot!
If you're targeting firefox, it has great SVG support, so you can now use SVG masks instead of CSS. Here is Mozillas documentation on how to do a mask in SVG Webkit masks aren't standards track - so I have a personal doubt that you'll ever see them cross-browser.
After struggling with this for many hours, I was finally able to apply a complex SVG path as a mask for a div element on my site, and it works in Firefox. Here's what I did:
First, for Webkit browsers, the solution was ideal, and I simply had to make a flattened png file with the same size (or really the same shape, could be different scale) as the div I want to mask, and with the area I want to be visible in black, and the parts I want clipped out transparent. Then, I added the following line to the CSS for the div element I want to mask:
-webkit-mask-box-image: url(path/to/mask.png);
That was easy! Now let's get to the fun part of getting this working in Firefox. For this method to work, the vector shape must be the exact same size as the area you want to mask. So my mask is a relatively complex vector path designed in Fireworks, and I need to get it converted to an SVG path, and thankfully, I have Illustrator available. Otherwise, use your favorite SVG editor to convert your shape path to SVG. If you're also using Fireworks to draw your vector shapes, you can right-click on the vector shape you want to use, go to 'Edit' -> 'Copy Path Outlines', and then you can paste it into a sufficiently large document in Illustrator, or whatever SVG editor you're using.
Next, you need to export it to an SVG file. In Illustrator, I used the 'Export for Web' function, selected SVG format, version 1.0, and exported it to an SVG file. The position and document size don't really matter, as we're just after the path description, and we'll discard the rest.
So, now open that SVG file you just made with a text editor, such as Text Edit or Notepad. You'll see some XHTML-formatted content, and one element in particular is something like:
<path fill-rule="evenodd" clip-rule="evenodd" d="M0,43v0.5V44v0.5v1V46v0.5v1V48v0..."/>
The d="..." portion will probably be many lines long for a complex shape. This is the only portion of this SVG file that we care about.
Next, we must embed an SVG mask describing this path into our site HTML. First, let's add the following elements to our HTML:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="maskid" maskUnits="userSpaceOnUse">
<path fill="white" d=""/>
</mask>
</defs>
</svg>
Now, we simply copy the contents of the d="" property of the path element from the SVG file we saved earlier (i.e. M0,43v0...) and paste into the same d="" property of the path element in the embedded SVG's mask element. Then, we can add the following entry to the CSS for the element we want to mask:
mask: url("#maskid");
That's it. The path should now be applied as a mask to the element you specified.
Here is the trick , you need to convert all points generated in your svg file to ratio that is equal the point path divided by mask dimension .
For easier explaination , i have made a quick tool to help designers convert their svg into a mask that is compatible with firefox , you can see a live demo on my website ( http://www.prollygeek.com ) , for example the facebook logo , and twitter logo are just masks , and here is the tool that you can use to convert your svg to a mask:
http://prollygeek.com/svg-mask/
for example:
<mask id="fb" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<path d="M236.626,120.827v27.295h-14.851c-4.416,0-7.225,1.204-8.63,3.612c-1.003,1.604-1.405,4.415-1.405,8.229v12.442h25.287l-3.01,27.494H211.74v79.273h-32.712v-79.273h-16.055v-27.494h16.055v-16.457c0-16.858,5.82-27.695,17.259-32.311
c5.619-2.208,10.436-2.811,15.453-2.811H236.626z"/>
will be turned to:
<mask id="fb" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<path d="M0.59,0.3v0.0675h-0.035c-0.01,0-0.0175,0.0025-0.02,0.0075c-0.0025,0.0025-0.0025,0.01-0.0025,0.02v0.03h0.0625l-0.0075,0.0675H0.5275v0.1975h-0.08v-0.1975h-0.04v-0.0675h0.04v-0.04c0-0.04,0.0125-0.0675,0.0425-0.08c0.0125-0.005,0.025-0.005,0.0375-0.005H0.59z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#ffffff;"/>
Please dont forget to add this attribute style="fill-rule:evenodd;clip-rule:evenodd;fill:#ffffff;"
and fill with any color , it doesnt matter.
afterwards link your mask to the css element you desire:
for example:
mask:url(images/fb.svg#fb);
the calculator is free to use , but please dont copy or publish anywhere else.
You can apply svg filters with css to HTML content in Gecko. Here is an example from a guy who likes to fiddle with mozilla code. It is from 2008 so it might be a bit outdated.
In SVG (for web-browsers), if i add a <text>-element and add some text to it the total rendered width of the text string will change depending on the scale of the text.
Lets say i add "mmmmmmmmmmmmmmmmmmmmmmmmmmA" as text, then i want to draw a vertical line(or other exactly positioned element) intersecting the very last character. Works fine but if i zoom out the text will become shorter or longer and the line will not intersect the text in the right place anymore. The error can be as much as +/- 5 characters width which is unacceptable. The error is also unpredictable, 150% and 160% zoom can add 3 characters length while 155% is 2 charlengths shorter.
My zoom is implemented as a scale-transform on the root element of my canvas which is a <g>.
I have tried to multiply the font-size with 1000x and scale down equally on the zoom-transform and vice versa in case it was a floating point error but the result is the same.
I found the textLength-attribute[1] which is supposed to adjust the total length so the text always end where i choose but it only works in Webkit. Firefox and Opera seems to not care at all about this value (haven't tried in IE9 yet).
Is there any way to render text exactly positioned without resorting to homemade filling of font-outlines?
[1] http://www.w3.org/TR/SVG11/text.html#TextElementTextLengthAttribute
Update
Snippet of the structure i'm using
<svg>
<g transform="scale(1)"> <!--This is the root, i'm changing the scale of this element to zoom -->
<g transform="scale(0.014)"> <!--This is a wrapper for multi-line text, scaling, other grouping etc -->
<text font-size="1000" textLength="40000">ABDCDEFGHIJKLMNOPQRSTUVXYZÅÄÖabcdefghijklmnopqrstxyzåäö1234567890</text>
</g>
</g>
Interesting, since the webkit builds I have seem to fail on textLength (w3c testcase). Could you post your example?
Speaking for Opera we do support the 'textLength' attribute, as documented here.
The other option you have is to use the getBBox method to find a good position for drawing your line, that should work in all the browsers.