I'm trying to create an SVG animation that smoothly blurs an element when it's clicked, then smoothly unblurs it when clicked again (and keeps alternating like that with each click).
So I have the following SVG:
<?xml version="1.0" standalone="no"?>
<svg width="1" height="1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="blurred">
<feGaussianBlur in="SourceGraphic" stdDeviation="0 0">
<animate attributeType="XML" attributeName="stdDeviation" from="0 0" to="0 50" dur="0.4s" fill="freeze" />
</feGaussianBlur>
</filter>
<filter id="unblurred">
<feGaussianBlur in="SourceGraphic" stdDeviation="0 50">
<animate attributeType="XML" attributeName="stdDeviation" from="0 50" to="0 0" dur="0.4s" fill="freeze" />
</feGaussianBlur>
</filter>
</defs>
</svg>
And then I toggle which filter is shown with these functions:
function blurItem(item) {
var background = item.find(".background");
background.css("filter", "url(css/filter.svg#blurred)");
}
function unblurItem(item) {
var background = item.find(".background");
background.css("filter", "url(css/filter.svg#unblurred)");
}
The first time I click the element, it smoothly blurs just like it should. But when I click again, it unblurs without any animation. And then from that point on, it just toggles between blurred and unblurred on each click without any animation.
Why does the animation only work on the very first click, and how do I get it to work each time?
Here's a fiddle: http://jsfiddle.net/7Pcdp/2/
For some reason, with the SVG inline in the HTML in the fiddle, the animation doesn't work at all. If I split it out into a separate .svg file, then it'll animate in Firefox, but again only the first time.
Once you click on the background the animation timeline runs from 0s to 0.4s and then stops as the animation is over. The next time you click the document timeline is still 0.4s so nothing happens as the animations only run from 0s to 0.4s.
One way around this is to make the animations start="indefinite" and then begin them using javascript by calling beginElement on the animations. Like so...
<div class="background" style="background-image: url('https://www.google.com/images/srpr/logo11w.png');"></div>
<svg>
<defs>
<filter id="blurred">
<feGaussianBlur in="SourceGraphic" stdDeviation="0 0">
<animate id="blurredAnimation" attributeType="XML" attributeName="stdDeviation" from="0 0" to="2 50" dur="0.4s" fill="freeze" begin="indefinite" />
</feGaussianBlur>
</filter>
<filter id="unblurred">
<feGaussianBlur in="SourceGraphic" stdDeviation="2 50">
<animate id="unblurredAnimation" attributeType="XML" attributeName="stdDeviation" from="2 50" to="0 0" dur="0.4s" fill="freeze" begin="indefinite" />
</feGaussianBlur>
</filter>
</defs>
</svg>
$(document).on("click", ".background", function(){ var background = $(this); toggleBlur(background); });
function toggleBlur(background) {
if (!(background.hasClass("blurred"))) {
background.addClass("blurred");
background.css({
filter: "url(#blurred)",
webkitFilter: "url(#blurred)"
});
document.getElementById("blurredAnimation").beginElement();
} else {
background.removeClass("blurred");
background.css({
filter: "url(#unblurred)",
webkitFilter: "url(#unblurred)"
});
document.getElementById("unblurredAnimation").beginElement();
}
};
I got the same problem on Safari. The animations worked well on click. They worked again in FF and Chrome (IE does not work at all), but not in Safari.
Safari just did the animation once, but never twice.
Workaround: After closing the menu (so the svg was in initial state again) i replaced the element with itself. After that the animation could be started again, as Safari started it "from scratch"
Only disadvantage: You need to replace the element with JavaScript.
This piece of code helped me out:
window.setTimeout(function(){
$('svg#button').replaceWith('<svg id="button" viewBox="-374 350 210 70"><polygon style="stroke:#dfdfdf;stroke-width:5;stroke-linejoin:round" fill="#eeeeee" points="-366.500 308.500, -366.500 253.500, -196.900 253.500, -171.500 281.000, -196.900 308.500, -366.500 308.500"><animate id="animation-to-check" begin="indefinite" fill="freeze" attributeName="points" dur="500ms" to="-366.500 497.500, -366.500 253.500, -171.500 253.500, -171.500 281.000, -171.500 497.500, -366.500 497.500" values="-366.500 308.500, -366.500 253.500, -196.900 253.500, -171.500 281.000, -196.900 308.500, -366.500 308.500;-366.500 308.500, -366.500 253.500, -171.500 253.500, -171.500 281.000, -171.500 308.500, -366.500 308.500;-366.500 497.500, -366.500 253.500, -171.500 253.500, -171.500 281.000, -171.500 497.500, -366.500 497.500"/><animate id="animation-to-star" begin="indefinite" fill="freeze" attributeName="points" dur="500ms" to="-366.500 308.500, -366.500 253.500, -196.900 253.500, -171.500 281.000, -196.900 308.500, -366.500 308.500" values="-366.500 497.500, -366.500 253.500, -171.500 253.500, -171.500 281.000, -171.500 497.500, -366.500 497.500;-366.500 308.500, -366.500 253.500, -171.500 253.500, -171.500 281.000, -171.500 308.500, -366.500 308.500;-366.500 308.500, -366.500 253.500, -196.900 253.500, -171.500 281.000, -196.900 308.500, -366.500 308.500;"/></polygon></svg>');
},700);
Maybe you could use a placeholder onload, so you donĀ“t need to load the svg-sources twice...
Related
I am a total newbie trying to make an interactive SVG - preferably without any external scripting. The effect that I am aiming for is to have one SVG element act as an interactive toggle to make another element appear and disappear.
Please find below a simple version where the text "Toggle" acts as the toggle. On click, this will animate the opacity attribute of the rectangle from 0 to 1 making it appear.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext.click" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
Any subsequent click will now just simply repeat that same animation. But I want any second (fourth, sixth, etc.) click to reverse the animation (i.e. make the rectangle disappear). In other words to truly act as a toggle.
Any advice on how to achieve this effect with as little code and/or invisible elements as possible would be greatly appreciated.
Thanks!
This is how I would do it: I'm using 2 overlapped text elements and I'm setting the pointer events to all or none on click: This way you'll click once on one text and next on the other.
The rect has 2 animate elements: one animation will start when you click on the first text, the second animation will start when clicking on the second text.
text{font-size:8.46667px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583;}
<svg width="300" viewBox="0 0 47.652294 10.096307" id="svg8">
<g id="layer1" transform="translate(-29.085516,-61.315985)">
<rect fill="#ff0000" opacity="0" id="rect" width="9.8317242" height="9.8317242" x="66.773796" y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext1.click" />
<animate attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="toggletext2.click" />
</rect>
<text x="29.085516" y="68.002762" id="toggletext2">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext1.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
<text x="29.085516" y="68.002762" id="toggletext1">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext2.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
</g>
</svg>
Add a second rectangle fade animation
<animate id="hide" attributeName="opacity" fill="freeze"
from="1" to="0" dur="2s" begin="indefinite" />
And add a JS trigger that toggles the animation of the appearance and disappearance of the rectangle
var svg_1 = document.getElementById("svg8"),
hide = document.getElementById("hide"),
visable = document.getElementById("visable");
let flag = true;
svg_1.addEventListener('click', function() {
if (flag == true) {
visable.beginElement();
flag = false;
} else {
hide.beginElement();
flag = true;
}
});
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate id="visable" attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="indefinite" />
<animate id="hide" attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="indefinite" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
Although I like the No-JavaScript pointer-events method; this is how I would do it:
When OP says: preferably without any external scripting.
I presume he means no 3rd party libraries.
So I would use a Custom Element <svg-toggle> (supported in all modern browsers)
that creates the SVG for any number of toggles you want
To toggle animation:
switch the from and to parameters on every click
restart the animation
<style>
svg {
display: inline-block; width: 30%; vertical-align: top;
cursor: pointer; background: teal; color: white;
}
</style>
<svg-toggle></svg-toggle>
<svg-toggle color="yellow"></svg-toggle>
<svg-toggle color="blue" label="Blue" duration=".5"></svg-toggle>
<script>
customElements.define('svg-toggle', class extends HTMLElement {
connectedCallback() {
this.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">
${this.getAttribute("label")||'Toggle'}</text>
<rect fill="${this.getAttribute("color")||'red'}" x='33' y="3" width="12" height="12">
<animate attributeName="opacity" dur="${this.getAttribute("duration")||2}s" from="0" to="1" fill="freeze" begin="indefinite"/>
</rect></svg>`;
this.animate = this.querySelector("animate");
this.onclick = (evt) => this.toggle();
}
toggle( // method, so can be called from Javascript
from = this.animate.getAttribute("from"), // optional from/to parameters
to = this.animate.getAttribute("to"),
) {
this.animate.setAttribute( "from", to );
this.animate.setAttribute( "to" , from );
this.animate.beginElement();
}
});
</script>
I don't want modern W3C standard Web Components mumbo jumbo...
Then stick the JavaScript on every SVG:
<svg
onclick="{
let a = this.querySelector('animate');
let from = a.getAttribute('from');
a.setAttribute('from',a.getAttribute('to'));
a.setAttribute('to',from);
a.beginElement();
}"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">Gold</text>
<rect fill="gold" x="33" y="3" width="12" height="12">
<animate attributeName="opacity" dur=".3s" from="0" to="1"
fill="freeze" begin="indefinite"></animate>
</rect>
</svg>
I don't want JavaScript
See Enxaneta his pointer-events answer
Why my animation doesn't start from the top to the bottom ? How to reverse it correctly ? I don't know what I should change. (I tried keyPoints="1;0" keyTimes="0;1" which didn't work)
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="350" viewBox="0 0 500 350"><path d="M404.88 470.22V79.69c-.2-19-14.21-33-17.52-36.19s-16.77-15.19-34.7-15.45h-1.11c-28.65.35-59.55-.12-319.52 0H28" stroke="#000" stroke-miterlimit="10" fill="none" id="motionPath"></path><rect id="circle" x="-25" y="-25" rx="15" ry="15" width="50" height="50"></rect><animateMotion xlink:href="#circle" from="50" to="450" dur="5s" begin="0s" repeatCount="1" rotate="auto" fill="freeze"><mpath xlink:href="#motionPath"></mpath></animateMotion></svg>
It is necessary to remove from =" 50 " to =" 450 " since the length of the path of movement is determined by the length of the path mpath
The direction of movement of an object along a path depends on two parameters
keyPoints="1;0" - movement from start to finish
keyTimes="0;1"
keyPoints="0;1" - movement from end to start
keyTimes="0;1"
In the example below, JS is used only to handle the event of pressing the control buttons: forward and back
var animation1 = document.getElementById("forward")
function forwardSVG(){
animation1.beginElement();
}
var animation2 = document.getElementById("back")
function backSVG(){
animation2.beginElement();
}
<div id="pathContainer4">
<button id="btn1" onclick="forwardSVG()">forward</button />
<button id="btn2" onclick="backSVG()">Back</button />
</div>
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="350" viewBox="50 0 500 350">
<path id="motionPath" d="M404.88 470.22V79.69c-.2-19-14.21-33-17.52-36.19s-16.77-15.19-34.7-15.45h-1.11c-28.65.35-59.55-.12-319.52 0H28" stroke="#000" stroke-miterlimit="10" fill="none" >
</path>
<rect id="circle" x="0" y="-25" rx="15" ry="15" width="50" height="50"></rect>
<!-- Forward motion animation -->
<animateMotion id="forward"
xlink:href="#circle"
dur="5s"
begin="indefinite"
rotate="auto"
fill="freeze"
repeatCount="1"
keyPoints="1;0"
keyTimes="0;1"
calcMode="linear">
<mpath xlink:href="#motionPath"></mpath>
</animateMotion>
<!-- Backward motion animation -->
<animateMotion id="back"
xlink:href="#circle"
dur="5s"
begin="indefinite"
rotate="auto"
fill="freeze"
repeatCount="1"
keyPoints="0;1"
keyTimes="0;1"
calcMode="linear">
<mpath xlink:href="#motionPath"></mpath>
</animateMotion>
</svg>
Here is the reverse you want.
I modified the shape a little but you can modify it back again.
Hope that this is the solution to your problem.
you can make it freeze too if you want.
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="350" viewBox="0 0 500 350">
<g>
<path stroke="#000" stroke-miterlimit="10" fill="none" id="motionPath"
d="M404.88 470.22V79.69c-.2-19-14.21-33-17.52-36.19s-16.77-15.19-34.7-15.45h-1.11c-28.65.35-59.55-.12-319.52 0H28"/>
<rect id="circle" x="-25" y="-25" rx="15" ry="15" width="50" height="60" fill="black"
stroke="black" stroke-width="1" transform="translate(-25,-10)">
<animateMotion path="M404.88 470.22V79.69c-.2-19-14.21-33-17.52-36.19s-16.77-15.19-34.7-15.45h-1.11c-28.65.35-59.55-.12-319.52 0H28"
begin= "0s" dur="5s" repeatCount="1" rotate="auto" fill="freeze"
keyPoints="1;0" keyTimes="0;1" calcMode="linear"/>
</rect>
</g>
</svg>
I have my SVG file with various animations written by me, i can't able to zoom image in image tag(I need it as an animation). In SVG circle tag works perfect for zoom in and zoom out animation. please anyone help me by giving your solution in pure SVG.
<image id="img_id" x="200" y="200" width="50" height="50" preserveAspectRatio="none" xlink:href="my svg image as vector code"/>
<animateTransform
xlink:href="#img_id"
begin="1s" values="-150,-150; 0,0" dur="0.5s"
type="translate"
attributeName="transform"
fill="freeze" additive="sum"/>
<animateTransform
xlink:href="#img_id"
begin="1s" values="2; 1" dur="0.5s"
type="scale" attributeName="transform"
fill="freeze" additive="sum"/>
My SVG code in JSfiddle!
Adjust the translate animation for the image till it zooms from its centre. I.e.
<svg version="1.1" width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<circle id="trigger" class="button" cx="150" cy="150" r="25" />
<animateTransform begin="1s" values="-150,-150; 0,0" dur="0.5s"
type="translate"
attributeName="transform"
fill="freeze"
additive="sum"/>
<animateTransform begin="1s" values="2; 1" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze" additive="sum"/>
</g>
<image id="img_id" x="213" y="233" width="50" height="50" preserveAspectRatio="none" xlink:href="data:image/png;base64,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"/>
<animateTransform
xlink:href="#img_id"
begin="1s" values="-238,-258; 0,0" dur="0.5s"
type="translate"
attributeName="transform"
fill="freeze" additive="sum"/>
<animateTransform
xlink:href="#img_id"
begin="1s" values="2; 1" dur="0.5s"
type="scale" attributeName="transform"
fill="freeze" additive="sum"/>
</svg>
I have created a simple inline SVG.
Using SMIL I have tried to animate the fill attribute to pink for all paths upon mouseover of the parent SVG id.
On mouseout I would like the fill to always reset.
I do not want the fill animation to repeat on mouseover. I just want it to run once and 'stop' (i.e. stay pink), but, only if the animation duration completes.
I have tried the following:
#logoSVG {
width: 100px;
}
<a href="javascript:void(0)" id="logo">
<svg version="1.1" id="logoSVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 113.7 62.2" enable-background="new 0 0 113.7 62.2" xml:space="preserve">
<path id="M" fill="#1E90FF" d="M16.1,38.9l-9-30.4H6.7C7.2,14.8,7.2,18.8,7.2,21v17.9H0V0h11.2l9,29.5l0,0L30,0h11.2v38.5h-7.6
V20.6c0-0.9,0-1.8,0-3.1c0-1.3,0-4,0.4-9h-0.4l-9.8,30.4L16.1,38.9L16.1,38.9z" />
<path id="A" fill="#1E90FF" d="M74.7,38.9l-2.7-9.4H58.2l-2.7,9.4h-9L60,0h9.8l13.9,38.9H74.7z M69.8,22.8c-2.7-8.5-4-13-4.5-14.3
c-0.4-0.9-0.4-1.8-0.9-2.7c-0.4,2.2-2.2,7.6-4.9,16.6h10.3V22.8z" />
<path id="T" fill="#1E90FF" d="M102.9,38.9h-8.1V7.2H84.6V0h29.1v6.7h-10.3v32.2H102.9z" />
<rect id="Line" y="55.9" fill="#1E90FF" width="113.7" height="6.3" />
<animate xlink:href="#M" attributeName="fill" from="#1E90FF" to="pink" dur="0.8s" begin="logoSVG.mouseover" end="logoSVG.mouseout" id="m-anim" />
<animate xlink:href="#A" attributeName="fill" from="#1E90FF" to="pink" dur="0.8s" begin="m-anim.begin + 0s" end="logoSVG.mouseout" id="a-anim" />
<animate xlink:href="#T" attributeName="fill" from="#1E90FF" to="pink" dur="0.8s" begin="m-anim.begin + 0s" end="logoSVG.mouseout" id="t-anim" />
<animate xlink:href="#Line" attributeName="fill" from="#1E90FF" to="pink" dur="0.8s" begin="m-anim.begin + 0s" end="logoSVG.mouseout" id="line-anim" />
</svg>
</a>
As you can see the fill does not 'stop' at the end.
Am I missing something?
Is mouseover/mouseout the right value to use to achieve this effect?
You can add a "fill" attribute to your -Tags, and set it to "freeze", e.g.:
<animate xlink:href="#M" attributeName="fill" from="#1E90FF"
to="pink" dur="0.8s" begin="logoSVG.mouseover"
end="logoSVG.mouseout" id="m-anim" fill="freeze"/>
From the docs:
freeze - The animation effect is "frozen" when the active duration of the animation is over for the remainder of the document duration (or until the animation is restarted).
Update
If mouse events are triggered correctly, the freezed fill wont change back.
Alternatively, you could animate each state explicitly:
change the color
keep the filling
change the fill back to the original color
I reduced the example to just one letter, for clarity:
#logoSVG {
border: 1px dashed #777;
width: 100px;
}
<a href="javascript:void(0)" id="logo">
<svg version="1.1" id="logoSVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 113.7 62.2" enable-background="new 0 0 113.7 62.2" xml:space="preserve">
<path id="M" fill="#1E90FF" d="M16.1,38.9l-9-30.4H6.7C7.2,14.8,7.2,18.8,7.2,21v17.9H0V0h11.2l9,29.5l0,0L30,0h11.2v38.5h-7.6
V20.6c0-0.9,0-1.8,0-3.1c0-1.3,0-4,0.4-9h-0.4l-9.8,30.4L16.1,38.9L16.1,38.9z" />
<animate xlink:href="#M" attributeName="fill" from="#1E90FF" to="pink" dur="0.8s" begin="logoSVG.mouseover" end="logoSVG.mouseout" id="m-anim" fill="freeze"/>
<animate xlink:href="#M" attributeName="fill" from="pink" to="pink" dur="0.8s" begin="logoSVG.mouseover+0.8s" end="logoSVG.mouseout" id="m-anim" fill="freeze"/>
<animate xlink:href="#M" attributeName="fill" from="#1E90FF" to="#1E90FF" begin="logoSVG.mouseout" end="logoSVG.mouseover" id="m-anim" fill="freeze"/>
</svg>
</a>
A sidenote: begin values like begin="m-anim.begin + 0s" seem not work in Firefox (Developer Edition 41.0a2 (2015-07-18), at least on my machine
The following code animates the img along the specific #pat path.
<switch>
<g i:extraneous="self">
<path id="pat" style="stroke:url(#grad);" class="mypath" d="
M144.668,123.467c0,0-13.001-133.999-143.668-121.665"/>
</g>
</switch>
<image xlink:href="http://m.kaon.com/icon/17001.png" width="30" height="30" x="-15" y="-15">
<animateMotion rotate="auto" dur="3s" repeatCount="indefinite">
<mpath xlink:href="#pat"/>
</animateMotion>
</image>
Is there any way to loop the animation indefinitely, but to have a delay inbetween. Like animate 0->1, wait 5s, animate 0-1.
Using this resource: http://www.w3.org/TR/SVG11/animate.html#AnimateMotionElement.
You could add another fake/pause element to link the begin/end...first one is just a pause that doesn't really do anything (so it doesn't vanish when its not on the path).
<animateTransform begin="myanim.end" id="pause" dur="3s" type="translate" attributeType="XML" attributeName="transform"/>
<animateMotion id="myanim" dur="6s" begin="0; pause.end" fill="freeze">
<mpath xlink:href="#theMotionPath"/>
</animateMotion>
Example fiddle