Trying to animate SVG gradient - javascript

I am using SVG to try and animate a gradient path - to create a tail / shooting star effect. In doing this, I want to animate an object at the front of the tail, which I have shown in my example below (the circles).
The example works barely in Google Chrome, haven't checked others... You can see I've got 5 circles/paths and only 1 of them is working properly. The curved one animates the gradient at a different speed to the object and the others don't work properly at all except for the "almost-horizontal" one.
Can someone please provide some insight into why this doesn't work, recommend a way I could do this and provide an example if possible?
I'm almost to the point where i'll just write my own render code in canvas and using a JS library... :(
<svg style="height: 400px; width: 100%" viewBox="0 0 500 200">
<path id="circlePath1" stroke-width="2" d="M10 100 Q 100 10, 150 80 T 300 100" stroke="url(#grad)" fill="transparent"></path>
<path id="circlePath2" stroke-width="2" d="M30 20 L 130 19" stroke="url(#grad)" fill="transparent"></path>
<path id="circlePath3" stroke-width="2" d="M30 10 L 130 10" stroke="url(#grad)" fill="transparent"></path>
<path id="circlePath4" stroke-width="2" d="M10 10 L 10 110" stroke="url(#grad)" fill="transparent"></path>
<path id="circlePath5" stroke-width="2" d="M10 20 L 20 110" stroke="url(#grad)" fill="transparent"></path>
<linearGradient id='grad'>
<stop stop-opacity="0" stop-color='#800'>
<animate attributeName="offset" dur="2s" values='-0.20;0.80' repeatCount="indefinite" ></animate>
</stop>
<stop stop-color='#800' stop-opacity=".5">
<animate attributeName="offset" dur="2s" values='-0.02;0.98' repeatCount="indefinite" ></animate>
</stop>
<stop stop-opacity="0.5" stop-color='#800'>
<animate attributeName="offset" dur="2s" values='-0;1' repeatCount="indefinite" ></animate>
</stop>
<stop stop-opacity="0" stop-color='#800'>
<animate attributeName="offset" dur="2s" values='-0;1' repeatCount="indefinite" ></animate>
</stop>
</linearGradient>
<circle id="c1" r="2.5" cx="" cy="" fill="#880000">
<animateMotion dur="2s" repeatCount="indefinite">
<mpath href="#circlePath1"></mpath>
</animateMotion>
</circle>
<circle id="c2" r="2.5" cx="" cy="" fill="#880000">
<animateMotion dur="2s" repeatCount="indefinite">
<mpath href="#circlePath2"></mpath>
</animateMotion>
</circle>
<circle id="c3" r="2.5" cx="" cy="" fill="#880000">
<animateMotion dur="2s" repeatCount="indefinite">
<mpath href="#circlePath3"></mpath>
</animateMotion>
</circle>
<circle id="c4" r="2.5" cx="" cy="" fill="#880000">
<animateMotion dur="2s" repeatCount="indefinite">
<mpath href="#circlePath4"></mpath>
</animateMotion>
</circle>
<circle id="c5" r="2.5" cx="" cy="" fill="#880000">
<animateMotion dur="2s" repeatCount="indefinite">
<mpath href="#circlePath5"></mpath>
</animateMotion>
</circle>
</svg>

In this attempt I use a radial gradient that is masked by the line to create the trail, then a separate dot.
<svg width="500" height="300" viewBox="0 0 500 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="motion-path" stroke-width="2" d="M202.4 58.3c-13.8.1-33.3.4-44.8 9.2-14 10.7-26.2 29.2-31.9 45.6-7.8 22.2-13.5 48-3.5 70.2 12.8 28.2 47.1 43.6 68.8 63.6 19.6 18.1 43.4 26.1 69.5 29.4 21.7 2.7 43.6 3.3 65.4 4.7 19.4 1.3 33.9-7.7 51.2-15.3 24.4-10.7 38.2-44 40.9-68.9 1.8-16.7 3.4-34.9-10.3-46.5-9.5-8-22.6-8.1-33.2-14.1-13.7-7.7-27.4-17.2-39.7-26.8-5.4-4.2-10.4-8.8-15.8-12.9-4.5-3.5-8.1-8.3-13.2-11-6.2-3.3-14.3-5.4-20.9-8.2-5-2.1-9.5-5.2-14.3-7.6-6.5-3.3-12.1-7.4-19.3-8.9-6-1.2-12.4-1.3-18.6-1.5-10.2-.3-20.2-1.5-30.3-1" stroke="#666" fill="none"/>
<mask id="path-mask">
<use xlink:href="#motion-path" stroke="#666"/>
</mask>
<symbol id="ball">
<circle id="ball" r="2.5" fill="#800">
<animateMotion dur="5s" repeatCount="indefinite">
<mpath xlink:href="#motion-path"/>
</animateMotion>
</circle>
</symbol>
<symbol id="trail">
<circle r="30" fill="url(#grad)">
<animateMotion dur="5s" repeatCount="indefinite" rotate="auto">
<mpath xlink:href="#motion-path"/>
</animateMotion>
</circle>
</symbol>
<linearGradient id="grad">
<stop offset="0" stop-opacity="0" stop-color="#800"/>
<stop offset=".5" stop-opacity=".8" stop-color="#800"/>
<stop offset=".5" stop-opacity="0" stop-color="#800"/>
</linearGradient>
</defs>
<use xlink:href="#ball"/>
<use xlink:href="#trail" mask="url(#path-mask)"/>
</svg>
It has its limitations (if the path gets too close you get the trail showing on both bits) but hopefully this gives you an idea to play with.

Related

Restart SVG animation sequence from Javascript

I'm trying to restart SVG animation sequence from Javascript. Restart-button below will broke SVG animation sequence. How to restart/reset entire sequence?
document.getElementById("button").addEventListener("click", function() {
document.getElementById("fore").beginElement();
});
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 150">
<path id="track" fill="none" stroke="#000000" stroke-width="1" stroke-dasharray="10,10" d="M 50 100 L 950 50"/>
<path id="plane" d="M-10 -10 L10 0L-10 10z" fill="red" />
<animateMotion xlink:href="#plane"
id="fore"
begin="0s;back.end"
dur="2s"
fill="freeze"
repeatCount="1"
rotate="auto"
keyPoints="0;1"
keyTimes="0;1"
><mpath xlink:href="#track" /></animateMotion>
<animateMotion xlink:href="#plane"
id="back"
begin="fore.end"
dur="2s"
fill="freeze"
repeatCount="1"
rotate="auto-reverse"
keyPoints="1;0"
keyTimes="0;1"
><mpath xlink:href="#track" /></animateMotion>
</svg>
<button id="button">RESTART</button>
You can use setCurrentTime on the entire svg element. I added an id of svgEl to the svg node and then when rest is clicked we do:
document.getElementById('svgEl').setCurrentTime(0);
Have a look at this:
document.getElementById("button").addEventListener("click", function() {
document.getElementById('svgEl').setCurrentTime(0);
});
<svg id="svgEl" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 150">
<path id="track" fill="none" stroke="#000000" stroke-width="1" stroke-dasharray="10,10" d="M 50 100 L 950 50"/>
<path id="plane" d="M-10 -10 L10 0L-10 10z" fill="red" />
<animateMotion xlink:href="#plane"
id="fore"
begin="0s;back.end"
dur="2s"
fill="freeze"
repeatCount="1"
rotate="auto"
keyPoints="0;1"
keyTimes="0;1"
restart="always"
><mpath xlink:href="#track" /></animateMotion>
<animateMotion xlink:href="#plane"
id="back"
begin="fore.end"
dur="2s"
fill="freeze"
repeatCount="1"
rotate="auto-reverse"
keyPoints="1;0"
keyTimes="0;1"
restart="always"
><mpath xlink:href="#track" /></animateMotion>
</svg>
<button id="button">RESTART</button>

How to combine two animateTransformation not silmutaneously but consecutively?

I have the following transformations
<svg height="205" width="365" xmlns="http://www.w3.org/2000/svg"> <!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ --> <g>
<title></title>
<rect fill="none" height="207" id="canvas_background" width="367" x="-1" y="-1"></rect> </g> <g>
<title></title>
<g id="svg_3"> <path class="hinh1" d="m22,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_1" stroke="#000" stroke-width="1.5" style="fill: rgb(92, 188, 214);stroke-linejoin: round;/* x: 100; *//* y: 100px; */"></path> <g transform="translate(-132.281 0)"><path class="hinh2" d="m207.0027,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_2" stroke="#000" stroke-width="1.5" transform="rotate(180 274.503 54.7665) translate(0 70.8138) translate(0 -82.7702)" style="fill: rgb(214, 92, 188); stroke-linejoin: round;">
</path>
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="0 56" begin="0s" dur="5s" repeatCount="indefinite" id="one">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="-185 0" begin="one.end" dur="5s" repeatCount="indefinite">
</animateTransform>
</g> </g> </g> </svg>
I want the right semicircle to go down THEN go left (not simultaneously) to snap to the left semicircle.
I found that, the following code does not work as I expect, only the second one is triggered. Isn't it the case that one.end has no meaning here?
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="0 56" begin="0s" dur="5s" repeatCount="indefinite" id="one">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="-185 0" begin="one.end" dur="5s" repeatCount="indefinite">
</animateTransform>
In addition, at the end of the animations, I want the right to stop for about 3s before repeating, how to do so?
Instead of using the to and for attributes you can animate between several values by using the values attribute where the values for the transformation are separates by semicolons:
<svg height="205" width="365" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="none" height="207" id="canvas_background" width="367" x="-1" y="-1"></rect>
</g>
<g id="svg_3">
<path class="hinh1" d="m22,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_1" stroke="#000" stroke-width="1.5" style="fill: rgb(92, 188, 214);stroke-linejoin: round;"></path>
<g>
<path class="hinh2" d="m207.0027,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_2" stroke="#000" stroke-width="1.5" transform="rotate(180 274.503 54.7665) translate(0 70.8138) translate(0 -82.7702)" style="fill: rgb(214, 92, 188); stroke-linejoin: round;">
</path>
<animateTransform attributeName="transform" attributeType="XML" type="translate" values="0 0;0 56;-185,56" begin="0s" dur="5s" repeatCount="1" fill="freeze" id="one">
</animateTransform>
</g>
</g>
</svg>

click event on svg refuses to play

I found this code at codepen and I tested on jsfiddle, on codepen but...when I add it to a localhost test page the click event doesn't do anything!
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
<!-- bar 1 -->
<path fill="#D8D8D8" d="M0,0 L6,0 L6,16 L0,16 L0,0 Z" id="bar1">
<animate xlink:href="#bar1"
attributeName="d"
from="M0,0 L6,0 L6,16 L0,16 L0,0 Z"
to="M0,0 L6,3.20001221 L6,12.7999878 L0,16 L0,0 Z"
dur="0.3s"
fill="freeze"
begin="startAnimation.begin" />
<animate xlink:href="#bar1"
attributeName="d"
from="M0,0 L6,3.20001221 L6,12.7999878 L0,16 L0,0 Z"
to="M0,0 L6,0 L6,16 L0,16 L0,0 Z"
dur="0.3s"
fill="freeze"
begin="reverseAnimation.begin" />
</path>
<!-- horizontal line -->
<path fill="#D8D8D8" d="M10,0 L16,0 L16,16 L10,16 Z" id="bar2">
<animate attributeName="d"
from="M10,0 L16,0 L16,16 L10,16 Z"
to="M5.9944458,3.20001221 L15,8 L15,8 L5.9944458,12.7999878 Z"
dur="0.3s"
fill="freeze"
begin="startAnimation.begin" />
<animate attributeName="d"
from="M5.9944458,3.20001221 L15,8 L15,8 L5.9944458,12.7999878 Z"
to="M10,0 L16,0 L16,16 L10,16 Z"
dur="0.3s"
fill="freeze"
begin="reverseAnimation.begin" />
</path>
<!-- controls -->
<!-- these are on top of the visible icon. Their radius changes depending on which is active
Opacity is set to 0 so you can't see them-->
<circle cx="16" cy="16" r="16" fill-opacity="0">
<animate dur="0.01s" id="startAnimation" attributeName="r" values="16; 0" fill="freeze" begin="click" />
<animate dur="0.01s" attributeName="r" values="0; 16" fill="freeze" begin="reverseAnimation.end" />
</circle>
<circle cx="16" cy="16" r="0" fill-opacity="0">
<animate dur="0.001s" id="reverseAnimation" attributeName="r" values="16; 0" fill="freeze" begin="click" />
<animate dur="0.001s" attributeName="r" values="0; 16" begin="startAnimation.end" fill="freeze" />
</circle>
</svg>
Does anybody had experienced sth similar?
I can't find what I do wrong here...
PS: I also added this style:
/*
* Play
* ----
*/
.play {
position: absolute;
z-index: 1000;
top: 35%;
left: 35%;
cursor: pointer;
margin: 0;
padding: 0.4em;
width: 30%;
height: 30%;
}
and modified the 1st line like
<svg class="play" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
still with no result!
On codepen, if you change the view to look at debug mode it will open a new tab with a full screen view of the page.
View the source and you will see that the page contains the normal HTML head and body tags.
Sample
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test - YouTube Play Pause Button</title>
<style>
body {
background: #111;
text-align: center;
}
svg {
margin-top: 45vh;
width: 40px;
height: 40px;
cursor: pointer;
}
</style>
</head>
<body translate="no">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
<!-- bar 1 -->
<path fill="#D8D8D8" d="M0,0 L6,0 L6,16 L0,16 L0,0 Z" id="bar1">
<animate xlink:href="#bar1"
attributeName="d"
from="M0,0 L6,0 L6,16 L0,16 L0,0 Z"
to="M0,0 L6,3.20001221 L6,12.7999878 L0,16 L0,0 Z"
dur="0.3s"
fill="freeze"
begin="startAnimation.begin" />
<animate xlink:href="#bar1"
attributeName="d"
from="M0,0 L6,3.20001221 L6,12.7999878 L0,16 L0,0 Z"
to="M0,0 L6,0 L6,16 L0,16 L0,0 Z"
dur="0.3s"
fill="freeze"
begin="reverseAnimation.begin" />
</path>
<!-- horizontal line -->
<path fill="#D8D8D8" d="M10,0 L16,0 L16,16 L10,16 Z" id="bar2">
<animate attributeName="d"
from="M10,0 L16,0 L16,16 L10,16 Z"
to="M5.9944458,3.20001221 L15,8 L15,8 L5.9944458,12.7999878 Z"
dur="0.3s"
fill="freeze"
begin="startAnimation.begin" />
<animate attributeName="d"
from="M5.9944458,3.20001221 L15,8 L15,8 L5.9944458,12.7999878 Z"
to="M10,0 L16,0 L16,16 L10,16 Z"
dur="0.3s"
fill="freeze"
begin="reverseAnimation.begin" />
</path>
<!-- controls -->
<!-- these are on top of the visible icon. Their radius changes depending on which is active
Opacity is set to 0 so you can't see them-->
<circle cx="16" cy="16" r="16" fill-opacity="0">
<animate dur="0.01s" id="startAnimation" attributeName="r" values="16; 0" fill="freeze" begin="click" />
<animate dur="0.01s" attributeName="r" values="0; 16" fill="freeze" begin="reverseAnimation.end" />
</circle>
<circle cx="16" cy="16" r="0" fill-opacity="0">
<animate dur="0.001s" id="reverseAnimation" attributeName="r" values="16; 0" fill="freeze" begin="click" />
<animate dur="0.001s" attributeName="r" values="0; 16" begin="startAnimation.end" fill="freeze" />
</circle>
</svg>
</body>
</html>

svg animationTransform from dynamic value

There is a circle. When you mouseover it increases from 1 to 2 when mouseout is reduced from 2 to 1.
With the rapid run the mouse over the visible circle of the race to widen the circle. The problem is that the animation start the circle from the values on which he managed will increase, and with the value 2. How to make so that when you mouseout the animation of reduction began with the value that had increased range.
<g transform="matrix(1 0 0 1 150 150)" id="sec7kpi">
<g transform="matrix(1 0 0 1 0 0)" id="sec7kpi-c1">
<ellipse fill="#372356" stroke="#27AE60" stroke-width="16" stroke-miterlimit="10" cx="0" cy="0" rx="71" ry="71" />
<text id="sec7text" x="-33" y="15" fill="#27AE60" font-family="LatoRegular" font-size="38.8363" pointer-events="none">KPI</text>
</g>
<defs>
<animateTransform attributeType="XML"
xlink:href="#sec7kpi-c1"
attributeName="transform"
type="scale"
dur="500ms"
from="1"
to="2"
restart="whenNotActive"
begin="mouseover"
fill="freeze"
id="c-hover"
/>
<animateTransform attributeType="XML"
xlink:href="#sec7kpi-c1"
attributeName="transform"
type="scale"
dur="500ms"
from="2"
to="1"
restart="whenNotActive"
begin="mouseout"
fill="freeze"
id="c-out"
/>
Simply delete the attribute from="2" from the second animateTransform element.
Because you are no longer providing a starting value for the mouseout animation, this has the effect of making this animation start at whatever value it has at the moment it is started, i.e. at the moment the mouse moves of the element. For example, if the user starts the initial mouseover animation by mousing over the element but then moves the mouse out when the scale has only reached 1.76, then the mouseout animation scaling will start at its current value, i.e. 1.76, not 2, and return to 1.
(To make the code you provided work in the code snippets below (at least in Firefox), I placed the minimal extra code required around your code to get it to work: i.e. I put <svg height="300"> at the top and </svg> at the bottom.)
Original problematic code with working snippet (essentially copied from your question):
<svg height="300">
<g transform="matrix(1 0 0 1 150 150)" id="sec7kpi">
<g transform="matrix(1 0 0 1 0 0)" id="sec7kpi-c1">
<ellipse fill="#372356" stroke="#27AE60" stroke-width="16" stroke-miterlimit="10" cx="0" cy="0" rx="71" ry="71" />
<text id="sec7text" x="-33" y="15" fill="#27AE60" font-family="LatoRegular" font-size="38.8363" pointer-events="none">KPI</text>
</g>
<defs>
<animateTransform attributeType="XML"
xlink:href="#sec7kpi-c1"
attributeName="transform"
type="scale"
dur="500ms"
from="1"
to="2"
restart="whenNotActive"
begin="mouseover"
fill="freeze"
id="c-hover"
/>
<animateTransform attributeType="XML"
xlink:href="#sec7kpi-c1"
attributeName="transform"
type="scale"
dur="500ms"
from="2"
to="1"
restart="whenNotActive"
begin="mouseout"
fill="freeze"
id="c-out"
/>
</svg>
Revised "fixed" code with working snippet:
<svg height="300">
<g transform="matrix(1 0 0 1 150 150)" id="sec7kpi">
<g transform="matrix(1 0 0 1 0 0)" id="sec7kpi-c1">
<ellipse fill="#372356" stroke="#27AE60" stroke-width="16" stroke-miterlimit="10" cx="0" cy="0" rx="71" ry="71" />
<text id="sec7text" x="-33" y="15" fill="#27AE60" font-family="LatoRegular" font-size="38.8363" pointer-events="none">KPI</text>
</g>
<defs>
<animateTransform attributeType="XML"
xlink:href="#sec7kpi-c1"
attributeName="transform"
type="scale"
dur="500ms"
from="1"
to="2"
restart="whenNotActive"
begin="mouseover"
fill="freeze"
id="c-hover"
/>
<animateTransform attributeType="XML"
xlink:href="#sec7kpi-c1"
attributeName="transform"
type="scale"
dur="500ms"
to="1"
restart="whenNotActive"
begin="mouseout"
fill="freeze"
id="c-out"
/>
</svg>

how to unite path and change shape in svg

I drew two arcs that together can be a circle.
I could not unite them.
1 - How to combine them?
path-1 example path-1
example path-2
path1= d="M75,250 C 100,50 250,50 275,250"
path2= d="M 275,250 C 275,450 75,450 75,250"
I want to replace the triangle in a circle.
2 - how to do it?
tringle shape: d="M-25,-12.5 L25,-12.5 L 0,-87.5 z" is inside the path.
Thanks..
my code:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<line class="line_svg" x1="75" y1="100" x2="275" y2="100" />
<line class="line_svg" x1="75" y1="250" x2="275" y2="250" />
<line class="line_svg" x1="75" y1="100" x2="75" y2="400" />
<line class="line_svg" x1="175" y1="100" x2="175" y2="400" />
<line class="line_svg" x1="275" y1="100" x2="275" y2="400" />
<line class="line_svg" x1="75" y1="400" x2="275" y2="400" />
<path id="path1"
d="M 275,250 C 275,450 75,450 75,250" fill="none" stroke="blue" stroke-width="7.06" />
<circle cx="75" cy="250" r="18" fill="blue" />
<circle cx="175" cy="100" r="18" fill="blue" />
<circle cx="275" cy="250" r="18" fill="blue" />
<circle cx="175" cy="400" r="18" fill="blue" />
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z" fill="yellow" stroke="red" stroke-width="7.06" >
<animateTransform
attributeName="transform"
begin="0s"
dur="10s"
type="rotate"
from="0 -100 -110"
to="360 150 150"
repeatCount="1" />
<animateMotion dur="11s" repeatCount="1" rotate="auto" >
<mpath xlink:href="#path1"/>
</animateMotion>
<circle id="pointA" cx="75" cy="250" r="5" />
</svg>​

Categories