middle-click on svg use element open new tab - firefox

With firefox, when I middle-click (or ctrl+click) on a use element, it open the xlink:href url in new tab (like a href)
bug or feature?
<svg viewBox="0 0 400 80">
<circle id="circle" cx="40" cy="40" r="30" fill="#29e"></circle>
<use xlink:href="#circle" transform="translate(70, 0)" style="stroke: red;"></use>
</svg>
<p>ctrl+click on right circle</p>

It's an unresolved bug that they're not really sure how to handle. Trigger is the xlink:href that gets somehow internally treated just like an A.href does (middle-click or ctrl + click open to a new tab.) One workaround is to bury the xlink:href element under an invisible rect:
<svg viewBox="0 0 400 80">
<circle id="circle" cx="40" cy="40" r="30" fill="#29e" />
<use xlink:href="#circle" transform="translate(70, 0)" style="stroke: red;" />
<rect style="opacity:0" x="80" y="10" width="60" height="60" />
</svg>
<p>ctrl+click on right circle - nothing happens</p>
If you have any events that need to trigger, you'll have to tie them to the invisible rect.

As a workaround for the bug linked in previous answer you may also use pointer-events: none CSS rule on the use element:
<svg viewBox="0 0 400 80">
<circle id="circle" cx="40" cy="40" r="30" fill="#29e"></circle>
<use xlink:href="#circle" transform="translate(70, 0)" style="stroke: red; pointer-events: none;"></use>
</svg>
<p>ctrl+click on right circle</p>
Or declare that all use elements must not be clickable with <style>use{pointer-events: none;}</style>.
Obviously, this workaround is applicable only in case the element has NOT to be interactive at all.

Related

SVG Animation puts back after completed [duplicate]

This question already has an answer here:
XML SVG - persist the end state of an animation
(1 answer)
Closed 1 year ago.
I just made a simple SVG animation using the tag "animate" inside the SVG tag group. It works nicely BUT right after the animation is completed, it goes back to the beginning, to the initial frame, then stops.
How should I modify my code inside the animate tag in order to keep the animation still in the last frame?
Thanks,
How should I modify my code inside the animate tag in order to keep
the animation still in the last frame?
To achieve this use the fill =" freeze " attribute
Below is an example without using fill =" freeze "
As in your description - the figure returns to its original state
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="200" viewBox="0 0 400 200" style="border:1px solid gray;" >
<circle cx="30" cy="100" r="30" fill="purple" >
<animate attributeName="cx" begin="svg1.click" dur="3s" values="30;300" />
</circle>
</svg>
Second example using fill =" freeze "
After the animation ends, the shape will remain in the last frame of the animation.
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="200" viewBox="0 0 400 200" style="border:1px solid gray;" >
<circle cx="30" cy="100" r="30" fill="purple" >
<animate attributeName="cx" begin="svg1.click" dur="3s" values="30;300" fill="freeze" />
</circle>
</svg>

SVG path : pattern fill not working in firefox and Safari

SVG path element not working in Firefox and Safari but it works in Chrome.
Why doesn't the path filled using pattern in Firefox and Safari?
<svg id="" xmlns="http://www.w3.org/2000/svg" height="500" width="600" style="position: absolute;">
<defs>
<pattern id="imgpattern" x="0" y="0" width="1" height="1" patternUnits="userSpaceOnUse">
<image width="600" xlink:href="https://i.pinimg.com/564x/e1/a5/b7/e1a5b7edacee456a4f3bc3e00c3c01d9.jpg"></image>
</pattern>
</defs>
<path d="M50,100 C50,100 100,100 100,50 L100,50 500,50 C500,50 500,100 550,100 L550,100 550,400 C550,400 500,400 500,450 L500,450 100,450 C100,450 100,400 50,400 L50,400 50,100 L50,100 0,100 0,0 0,425 L0,425 50,425 C50,425 75,425 75,450 L50,450 50,425 0,425 0,500 525,500 525,450 C525,450 525,425 550,425 L550,425 550,450 525,450 525,500 600,500 600,75 550,75 C550,75 525,75 525,50 L525,50 550,50 550,75 600,75 600,0 75,0 75,50 C75,50 75,75 50,75 L50,50 75,50 75,0 0,0 0,100" fill="#ff0000;" stroke="#F000" stroke-width="1px" style="fill:url(#imgpattern)"></path>
</svg>
There is no height attribute on the image. SVG 2 allows width/height to be omitted but only Blink has implemented this part of SVG 2 so far.
You also have a redundant fill on the rect (as you're applying a pattern fill as a style)
<svg id="" xmlns="http://www.w3.org/2000/svg" height="500" width="600" style="position: absolute;">
<defs>
<pattern id="imgpattern" x="0" y="0" width="1" height="1" patternUnits="userspaceOnUse">
<image width="600" height="600" xlink:href="https://i.pinimg.com/564x/e1/a5/b7/e1a5b7edacee456a4f3bc3e00c3c01d9.jpg"></image>
</pattern>
</defs>
<path d="M50,100 C50,100 100,100 100,50 L100,50 500,50 C500,50 500,100 550,100 L550,100 550,400 C550,400 500,400 500,450 L500,450 100,450 C100,450 100,400 50,400 L50,400 50,100 L50,100 0,100 0,0 0,425 L0,425 50,425 C50,425 75,425 75,450 L50,450 50,425 0,425 0,500 525,500 525,450 C525,450 525,425 550,425 L550,425 550,450 525,450 525,500 600,500 600,75 550,75 C550,75 525,75 525,50 L525,50 550,50 550,75 600,75 600,0 75,0 75,50 C75,50 75,75 50,75 L50,50 75,50 75,0 0,0 0,100" stroke="#F000" stroke-width="1px" style="fill:url(#imgpattern)"></path>
</svg>

Why does the SVG animation stop when using xlink:href for external file

For some reason my spinner.svg is not animating when using xlink:href. Embedding the SVG on the page and using xlink:href seems to work fine, as the snippet below shows.
The problem: static (and solid!) spinner instead of animation
Why are the animation tags of the SVG suddenly not taking effect? The reference must be working since the image is actually displaying.
EDIT: Could this have to do with the shadow dom and xref?
According to Sara Soueidan "The target element must be part of the current SVG document fragment". I might be overloading what "document fragment" means, but to me document fragments belong in Shadow DOM land, and I suspect that SMIL animations might not work when using <use> statements due to this?
Working versions
.xlinked {
color: green;
}
img {
color: red; // not taking effect - of course! just a test.
}
.embedded {
color: blue;
}
<h1>xlink local</h1>
<svg class="xlinked">
<!-- could not get this external reference to work?
<use xlink:href="http://imgh.us/spinner_1.svg" />
-->
<use xlink:href="#spinner" />
</svg>
<h1>embedded</h1>
<div class="embedded">
<svg id="embedded" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<circle cx="50" cy="50" r="45" stroke="rgba(43,43,43,0.3)" fill="none" stroke-width="10" stroke-linecap="round"/>
<circle cx="50" cy="50" r="45" stroke="currentColor" fill="none" stroke-width="6" stroke-linecap="round">
<animate attributeName="stroke-dashoffset" dur="2s" repeatCount="indefinite" from="0" to="502"/>
<animate attributeName="stroke-dasharray" dur="2s" repeatCount="indefinite" values="150.6 100.4;1 250;150.6 100.4"/>
</circle>
</svg>
</div>
<h1>img</h1>
<img src="http://imgh.us/spinner_1.svg" />
<h1>External absolute xlink (not working)</h1>
<svg>
<!-- could not get this external reference to work. should be the same as a local reference? -->
<use xlink:href="http://imgh.us/spinner_1.svg" />
</svg>
<h1>Source SVG with symbols for xlink reference </h1>
<svg xmlns="http://www.w3.org/2000/svg"><symbol id="spinner" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"><circle cx="50" cy="50" r="45" stroke="rgba(43,43,43,0.3)" fill="none" stroke-width="10" stroke-linecap="round"/><circle cx="50" cy="50" r="45" stroke="currentColor" fill="none" stroke-width="6" stroke-linecap="round"><animate attributeName="stroke-dashoffset" dur="2s" repeatCount="indefinite" from="0" to="502"/><animate attributeName="stroke-dasharray" dur="2s" repeatCount="indefinite" values="150.6 100.4;1 250;150.6 100.4"/></circle></symbol></svg>
In SVG1.1, Use element requires reference to SVG fragment not SVG URL. Try to add id attribute to root svg element of external SVG file and add hash string to href value of use element, like this.
external svg(spinner_1.svg)
<svg xmlns="http://www.w3.org/2000/svg" id="root">
<!--svg structure-->
</svg>
html uses external SVG file
<svg>
<use xlink:href="http://imgh.us/spinner_1.svg#root" />
</svg>
Note:In SVG2, you can set SVG URL to href attribute of use element. See https://www.w3.org/TR/2016/CR-SVG2-20160915/struct.html#UseElement

How to animate the svg rectangle to grow like music wave?

I have a below code,
<div id="akbar">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
width="400" height="200" viewBox="0 0 400 200">
<g transform="scale(1,-1) translate(0,-200)">
<rect x="50" y="0" fill="#f00" width="100" height="100">
<animate attributeName="height"
from="0"
to="100"
dur="0.5s"
fill="freeze" />
</rect>
<rect x="150" y="0" fill="#f70" width="100" height="200">
<animate
attributeName="height"
from="0"
to="200"
dur="0.5s"
fill="freeze" />
</rect>
<rect x="250" y="0" fill="#ec0" width="100" height="150">
<animate
attributeName="height"
from="0"
to="150"
dur="0.5s"
fill="freeze" />
</rect>
</g>
</svg>
</div>
I would like to animate the svg rectangle to grow like music waves.
How can I achieve that?
I need this behavior
You can achieve it using
values,
keyTimes
and keySplines
attributes of an <animate> tag.
JSfiddle example.
I stripped your example to single column only:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
width="400" height="200" viewBox="0 0 400 200">
<g transform="scale(1,-1) translate(0,-200)">
<rect x="50" y="0" fill="#f00" width="100" height="100">
<animate
attributeName="height"
from="0"
to="100"
dur="1s"
fill="freeze"
values="0; 200; 150; 160; 150; 160"
keyTimes="0; 0.2; 0.4; 0.6; 0.8; 1"
keySplines=".42 0 1 1;
0 0 .59 1;
.42 0 1 1;
0 0 .59 1;
.42 0 1 1;
0 0 .59 1;"
/>
</rect>
</g>
</svg>
As it is not perfect yet, you can play around with the attributes to adjust the timing better (keySplines especially) and make it more music waves like.
As you can see on the provided example, single column steps of movements are:
All the way from bottom to top
Then, from top to ~83% of height
Then, from ~83% to ~88%,
Then, from ~88% to ~83%,
Then, from ~83% to ~88%
I guess that increasing the difference between those repeating percentage numbers (83 and 88) will give you slightly better effect than mine (which is based on 75% and 80%, easier to calculate on widht: 200px), but it is close.
Also take a look at CSS tricks article on SVG animation, it is very thorough and covers all the details about mentioned attributes - and much more.

SVG Filter causes clipping of SVG with viewbox in Firefox

I am trying to create a resizable SVG shape, with a 'glow' effect when it is selected using a gaussian filter. When I try to apply the filter as below, in Firefox (tried on v39+), the filter seems to cause the rectangle to be clipped at the bottom as soon as the height of the SVG element is > about 490. This doesn't happen in chrome though. If the filter is removed, the rectangle is not clipped.
I've mucked around for hours trying various combinations for the filter effect region parameters, but can't seem to find anything that works for arbitrary sizes of the SVG element. Putting the filter on the g element seems to work, but here are going to be other children that I don't want the filter to apply to.
What am I missing and how can I make this work?
Thanks,
Dave
<html>
<body>
<div style = "width: 100%; height: 100%">
<svg style = "width: 100%; height: 100%">
<defs>
<symbol id="rectangle">
<polygon vector-effect="non-scaling-stroke" points="3,3 103,3 103,53 3,53"></polygon>
</symbol>
</defs>
<filter id="nodeGlow" width="100" height="100">
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<g>
<svg style="fill: rgb(0, 251, 255);
stroke: rgb(30, 30, 30);
stroke-width : 1.5px;
filter: url("#nodeGlow");"
y="0" x="0"
height="500" width="200"
class="node" preserveAspectRatio="none"
viewBox="0 0 106 56">
<use xlink:href="#rectangle"></use>
</svg>
</g>
</svg>
</div>
</html>
</body>
Update: Robert's suggestion to add another <g> element did the trick, although I put it around the <svg> element rather than the <use> element because the blur effect looked poor when scaled up if it was around the <use>. I didn't add it to the existing <g>, cause there will be other children of that one that shouldn't have the filter.
Wrap the use in a <g> element and put the filter on that, or put the filter directly on the <use> element.
html, body, div {
width: 100%;
height: 100%;
}
<div>
<svg width="100%" height="100%">
<defs>
<symbol id="rectangle">
<polygon vector-effect="non-scaling-stroke" points="3,3 103,3 103,53 3,53"></polygon>
</symbol>
</defs>
<filter id="nodeGlow" width="100" height="100">
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<g>
<svg style="fill: rgb(0, 251, 255);
stroke: rgb(30, 30, 30);
stroke-width : 1.5px;"
height="500" width="200"
class="node" preserveAspectRatio="none"
viewBox="0 0 106 56">
<g style="filter: url(#nodeGlow);">
<use xlink:href="#rectangle"></use>
</g>
</svg>
</g>
</svg>
</div>
Putting the filter on something that has a viewBox is unlikely to work as the viewBox changes the co-ordinate system of its children but it doesn't change the element's co-ordinate system. Firefox is actually working properly.

Resources