Related
I'm trying to animate an svg path for about 3 days now..
When i use the <animate> tag, the transition happens however it does so without any animation just from position A to position B.
I'd like to have a transition in between both so that is appears smoothly. What should I do ?
<div class="container">
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 167 1888.69">
<defs>
<style>
.cls-1 {
fill: #f2f2f2;
}
.cls-2 {
fill: #65bec0;
}
.cls-3 {
fill: #88d3cd;
}
.cls-4 {
fill: #60b9bc;
}
</style>
</defs>
<path id="glass" class="cls-1" d="M927.2,52.82c16.15,0,30.77,5.53,41.37,14.51s17.13,21.38,17.13,35.08l.3,1620.4c0,27.38-26.19,49.6-58.49,49.6-16.15,0-30.77-5.53-41.37-14.51S869,1736.52,869,1722.83l-.3-1620.4C868.71,75,894.9,52.83,927.2,52.82Z" transform="translate(-819 -52.82)"/>
<path class="cls-2" d="M881.46,1086.43h.09l-.09.06Z" transform="translate(-819 -52.82)"/>
<path id="back-liquid" class="cls-3" d="M925.15,1767.18c27.63.11,50.13-21.59,50.23-48.44L977,1285.27l.51-294.54s-26.11-2.52-49.22-16.49c-12.79-7.73-48.11,12.32-55.73,15.79l3.75,449.17,0,289.36a48.12,48.12,0,0,0,13.45,24.25A50.6,50.6,0,0,0,925.15,1767.18Z" transform="translate(-819 -52.82)"/>
<g id="front-liquid">
<path class="cls-4" transform="translate(-819 -52.82)">
<animate
id="poi_front_1"
attributeName="d"
values="M929.78,1765.31c-29.07.12-52.74-21.56-52.87-48.42l-2-433.46-.74-294.54s28.27,1.81,51-14.37c14.77-10.5,47,4.34,53.86,15.48l1.87,447.29.17,289.36A47.56,47.56,0,0,1,967,1750.91,54.74,54.74,0,0,1,929.78,1765.31Z;
m 929.78,1765.31 c -29.07,0.12 -52.74,-21.56 -52.87,-48.42 l -2,-433.46 -2.35,-293.4 c 0,0 29.04531,-29.79622 50.10593,-17.59673 31.46382,10.78462 34.47963,16.02568 55.52938,6.71575 L 980.9,1437.29 l 0.17,289.36 c -2.14495,9.3171 -7.04817,17.7714 -14.07,24.26 -10.15255,9.3127 -23.4433,14.4547 -37.22,14.4Z"
begin="0s; poi_front_2.end"
dur="1s"
/>
<animate
id="poi_front_2"
attributeName="d"
values="m 929.78,1765.31 c -29.07,0.12 -52.74,-21.56 -52.87,-48.42 l -2,-433.46 -2.35,-293.4 c 0,0 29.04531,-29.79622 50.10593,-17.59673 31.46382,10.78462 34.47963,16.02568 55.52938,6.71575 L 980.9,1437.29 l 0.17,289.36 c -2.14495,9.3171 -7.04817,17.7714 -14.07,24.26 -10.15255,9.3127 -23.4433,14.4547 -37.22,14.4 z;
M929.78,1765.31c-29.07.12-52.74-21.56-52.87-48.42l-2-433.46-.74-294.54s28.27,1.81,51-14.37c14.77-10.5,47,4.34,53.86,15.48l1.87,447.29.17,289.36A47.56,47.56,0,0,1,967,1750.91,54.74,54.74,0,0,1,929.78,1765.31Z"
begin="poi_front_1.end"
dur="1.5s"
/>
</path>
</g>
</svg>
</div>
html,body {width:100%; height:100%;}
.container{
width: 80%;
height: 80vh;
margin:auto;
}
svg {
width: 60%;
height:80vh;
margin: auto;
}
Here is a codepen demo of my svg : https://codepen.io/knudsem/pen/oNxoxrB
edit: i tried to reorganize the values, but still no luck. I don't get it, what am I missing?
Two observations:
You don't need 2 animations. You can use instead a list of 3 values for the animation: values ="v1;v2;v1" This together with repeatCount="indefinite" will do the trick.
Secondly: in this case the paths should be identical except the C and the S command in the middle. You need to keep the same commands in the same order, changing only the y value for the control points of the curves.
Also since I've changed the d attribute manually I've transformed it to all absolute using this converter: https://codepen.io/leaverou/pen/RmwzKv
<svg viewBox="0 850 167 1888.69">
<g id="front-liquid">
<path transform="translate(-819 -52.82)" stroke="red" stroke-width="5" fill="none" d="
M929.78,1765.31
C900.71,1765.43,877.04,1743.75,876.91,1716.89
L874.91,990.03
C872.5,990 901.6,950.2,922.7,972.4
S957.1,988.4,978.2,979.1
L980.9,1726.65
C978.925,1735.9671,974.022,1744.42,967,1750.91
C956.847,1760.2227,943.56,1765.3647,929.78,1765.31 Z">
<animate attributeName="d" values="M929.78,1765.31
C900.71,1765.43,877.04,1743.75,876.91,1716.89
L874.91,990.03
C872.5,990 901.6,988.2 922.7,972.4
S957.1,960 978.2,979.1
L980.9,1726.65
C978.925,1735.9671,974.022,1744.42,967,1750.91
C956.847,1760.2227,943.56,1765.3647,929.78,1765.31 Z;
M929.78,1765.31
C900.71,1765.43,877.04,1743.75,876.91,1716.89
L874.91,990.03
C872.5,990 901.6,950.2,922.7,972.4
S957.1,988.4,978.2,979.1
L980.9,1726.65
C978.925,1735.9671,974.022,1744.42,967,1750.91
C956.847,1760.2227,943.56,1765.3647,929.78,1765.31 Z;
M929.78,1765.31
C900.71,1765.43,877.04,1743.75,876.91,1716.89
L874.91,990.03
C872.5,990 901.6,988.2 922.7,972.4
S957.1,960 978.2,979.1
L980.9,1726.65
C978.925,1735.9671,974.022,1744.42,967,1750.91
C956.847,1760.2227,943.56,1765.3647,929.78,1765.31 Z" begin="0s;" dur="1s" repeatCount="indefinite" />
</path>
</g>
</svg>
I've removed the non animated paths and I've changed the viewBox value so that I'd be able to see the relevant part of the shape. You can change back to what you had,
The moon needs to move in that path same as the one with id of trajectory around the planet. But it is moving randomly (as if it's celebrating 4/20).
Please find the attached code.
.moon {
offset-path: path('m159.39 54.867a71.83 20.37 0 0 1-71.83 20.37 71.83 20.37 0 0 1-71.83-20.37 71.83 20.37 0 0 1 71.83-20.37 71.83 20.37 0 0 1 71.83 20.37z');
animation: revolve 10s 1s infinite ease-in-out forwards;
}
#keyframes revolve {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
<svg width="169.31" height="115.66" viewBox="0 0 169.31 115.66">
<circle cx="87.56" cy="54.867" r="45.855" fill="#ff4141" />
<circle class="moon" cx="18.051" cy="54.867" r="8.092" fill="#ff9900" />
<path
id="trajectory"
d="m18.051 54.867c1.9043-12.055 45.047-20.455 69.073-20.601 25.048-0.15208 64.422 2.9195 72.266 20.601-6.7091 16.516-45.54 20.472-69.791 20.552-24.814 0.082685-67.739-4.5793-71.548-20.552z"
fill="none" stroke-width=".5px" stroke="#000000" />
</svg>
offset-path is not yet supported enough by browsers caniuse.com
To realize the moon moving along a trajectory, consider using animateMotion
<svg width="169.31" height="115.66" viewBox="0 0 169.31 115.66">
<circle cx="87.56" cy="54.867" r="45.855" fill="#ff4141" />
<circle class="moon" cx="0" cy="0" r="8.092" fill="#ff9900" >
<animateMotion begin="0s"
dur="12s" repeatCount="3" fill="freeze" restart="whenNotActive" >>
<mpath xlink:href="#trajectory" />
</animateMotion>
</circle>
<path
id="trajectory"
d="m18.051 54.867c1.9043-12.055 45.047-20.455 69.073-20.601 25.048-0.15208 64.422 2.9195 72.266 20.601-6.7091 16.516-45.54 20.472-69.791 20.552-24.814 0.082685-67.739-4.5793-71.548-20.552z"
fill="none" stroke-width=".5px" stroke="#000000" />
</svg>
I know how to animate a clip-path defined directly in CSS, but I don't understand how to do it when the clip-path is referenced from an SVG clipPath element.
I have been experimenting with simple clip-path animations using just CSS, until I realized you can't define a compound-path as a clip-path directly there, so I turned to SVG's clipPath which allows defining multiple paths. But then the animation doesn't work, that is, there is no smooth transition.
Here is what I'm trying...
HTML
<svg>
<defs>
<clipPath id="shape--start">
<polygon points="0,100 22.222,133.333 8.333,147.222 -13.889,113.889 -47.222,91.667 -33.333,77.778"/>
</clipPath>
<clipPath id="shape--end">
<polygon points="144.444,-44.444 166.667,-11.111 152.778,2.778 130.556,-30.556 97.222,-52.778 111.111,-66.667"/>
</clipPath>
</defs>
</svg>
CSS
#keyframes shape {
0% { clip-path: url(#shape--start) }
100% { clip-path: url(#shape--end) }
}
To clarify more, if I use something like
CSS
#keyframes shape {
0% { clip-path: polygon(-44% 5%, -14% 5%, 15% 95%, -15% 95%) }
100% { clip-path: polygon(90% 5%, 120% 5%, 149% 95%, 119% 95%) }
}
it works as expected, but I would like to use SVG for the more complex compound paths.
Thanks for your time and any help in advance!
You need to animate the SVG itself using animate
.box {
width:300px;
height:200px;
background:red;
clip-path: url(#shape--start);
}
<svg width=0 height=0>
<defs>
<clipPath id="shape--start">
<polygon points="0,100 22.222,133.333 8.333,147.222 -13.889,113.889 -47.222,91.667 -33.333,77.778">
<animate attributeType="XML" attributeName="points"
from="0,100 22.222,133.333 8.333,147.222 -13.889,113.889 -47.222,91.667 -33.333,77.778"
to="144.444,-44.444 166.667,-11.111 152.778,2.778 130.556,-30.556 97.222,-52.778 111.111,-66.667"
dur="2s" repeatCount="indefinite"/>
</polygon>
</clipPath>
</defs>
</svg>
<div class="box">
</div>
Animation option using animateTransform
.box {
width:300px;
height:200px;
background:red;
clip-path: url(#shape--start);
}
<svg width="0" height="0">
<defs>
<clipPath id="shape--start">
<polygon points="0,100 22.222,133.333 8.333,147.222 -13.889,113.889 -47.222,91.667 -33.333,77.778">
<animateTransform attributeType="XML" attributeName="transform" type="translate"
values="0,100;144.444,-44.444"
dur="2s" repeatCount="indefinite"/>
</polygon>
</clipPath>
</defs>
</svg>
<div class="box">
</div>
Roundtrip animation
.box {
width:300px;
height:200px;
background:red;
clip-path: url(#shape--start);
}
<svg width="0" height="0">
<defs>
<clipPath id="shape--start">
<polygon points="0,100 22.222,133.333 8.333,147.222 -13.889,113.889 -47.222,91.667 -33.333,77.778">
<animateTransform attributeType="XML" attributeName="transform" type="translate"
values="0,100;144.444,-44.444;0,100"
dur="2s" repeatCount="indefinite"/>
</polygon>
</clipPath>
</defs>
</svg>
<div class="box">
</div>
I need flexible rotating centered SVG.
Problem is if use
<svg width="100%">
with rotation, browser window start resizing itself on svg rotation.
If i delete "width="100%"", than SVG will svg will not shrink on horizontal window resize.
Any ideas how to fix it?
Codesandbox example.
Putting the animation inside the svg is a solution.
<svg
viewBox="0 0 29.892 29.892"
width="100%"
height="100vh"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g>
<path
d="m14.946 0c-8.254 0-14.946 6.692-14.946 14.946 0 8.255 6.692 14.946 14.946 14.946s14.946-6.691 14.946-14.946c-1e-3 -8.254-6.692-14.946-14.946-14.946zm0 26.58c-6.425 0-11.634-5.208-11.634-11.634 0-6.425 5.209-11.634 11.634-11.634s11.633 5.209 11.633 11.634c0 6.426-5.208 11.634-11.633 11.634z"
opacity=".2"
/>
<path d="m20.758 4.878 1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012v3.312c2.119 0 4.1 0.576 5.812 1.566z"/>
<animateTransform repeatCount="indefinite" begin="0s" dur="5s" attributeName="transform" type="rotate" from="0 14.946 14.946" to="360 14.946 14.946" />
</g>
</svg>
If you want css to control the animation, you'd still have to group the paths within the svg. You can then target the group in css like below.
#circle {
animation: rotate 2s linear infinite;
transform-origin: 50% 50%
}
#keyframes rotate {
to {
transform: rotate(360deg);
}
}
<svg
viewBox="0 0 29.892 29.892"
width="100%"
height="100vh"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g id="circle">
<path
d="m14.946 0c-8.254 0-14.946 6.692-14.946 14.946 0 8.255 6.692 14.946 14.946 14.946s14.946-6.691 14.946-14.946c-1e-3 -8.254-6.692-14.946-14.946-14.946zm0 26.58c-6.425 0-11.634-5.208-11.634-11.634 0-6.425 5.209-11.634 11.634-11.634s11.633 5.209 11.633 11.634c0 6.426-5.208 11.634-11.633 11.634z"
opacity=".2"
/>
<path d="m20.758 4.878 1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012v3.312c2.119 0 4.1 0.576 5.812 1.566z" />
</g>
</svg>
I got this svg exported from Adobe Illustrator.
<?xml-stylesheet href="star.css" type="text/css"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<g id="star">
<path id="star-1" class="st0" d="M37.9,27.9L49.3,5c0.3-0.6,0.8-0.6,1.1,0l11.3,22.9c0.3,0.6,1.1,0.9,1.7,0.7
c0.7-0.2,0.9-0.8,0.6-1.5L52,2.7c-0.5-1-1.3-1.6-2.2-1.6c-0.9,0-1.7,0.6-2.2,1.6L35.9,26.6c-0.3,0.6-0.1,1.4,0.5,1.7
C36.9,28.7,37.6,28.5,37.9,27.9z"/>
<path id="star-2" class="st0" d="M71.3,31.8c-0.7-0.1-1.2,0.1-1.3,0.5c0,0.2-0.1,0.4-0.1,0.6c-0.2,0.7,0.1,1.2,0.7,1.3l26.2,3.8
L77.9,56.7c-0.5,0.5-0.4,1.1,0.1,1.6c0.5,0.5,1.1,0.7,1.6,0.2l19.1-18.6c0.8-0.8,1.1-1.8,0.9-2.6c-0.3-0.9-1.1-1.4-2.2-1.6
L71.3,31.8z"/>
<path id="star-3" class="st0" d="M76.9,66.8c-0.1-0.7-0.8-1.2-1.4-1.1c0,0,0,0,0,0c-0.7,0.1-1.1,0.7-1,1.4l4.5,26.3L55.4,81.1
c-0.6-0.3-1.4-0.1-1.6,0.6c0,0,0,0,0,0c-0.3,0.6,0,1.4,0.6,1.7l23.4,12.3c0.5,0.3,1,0.4,1.5,0.4c0.7,0,1.2-0.3,1.6-0.7
c0.3-0.4,0.7-1.1,0.5-2.3L76.9,66.8z"/>
<path id="star-4" class="st0" d="M44.7,80.9l-24,12.6l4.5-26.3c0.1-0.7-0.3-1.3-1-1.5c0,0,0,0,0,0c-0.7-0.1-1.3,0.3-1.4,1
l-4.5,26.4c-0.2,1.2,0.2,1.9,0.5,2.3c0.7,0.8,1.9,1,3.1,0.3l23.7-12.5c0.6-0.3,1-1.1,0.7-1.7c0,0,0-0.1,0-0.1
C46,80.7,45.3,80.5,44.7,80.9z"/>
<path id="star-5" class="st0" d="M21.9,56.8L2.7,38.1l26.5-3.8c0.7-0.1,1.2-0.7,1-1.4c-0.2-0.6-0.8-1.1-1.5-1L2.3,35.6
c-1.1,0.2-1.9,0.8-2.2,1.6c-0.3,0.9,0,1.8,0.9,2.6l19.4,18.9c0.5,0.5,1.2,0.4,1.7-0.1c0,0,0,0,0,0C22.5,58.1,22.4,57.3,21.9,56.8z
"/>
</g>
</svg>
Here is what i'm trying to accomplish, it should just simply draw from point A to point B, starting from 1 and ends with 5.
And this is what my css looks like:
#star{
fill-opacity: 0;
stroke: #37475B;
stroke-width: 1;
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw-star 10s linear forwards;
}
#keyframes draw-star {
to {
stroke-dashoffset: 0;
}
}
I am pretty much new to SVG animation, or even SVG itself. To be honest I have no idea what i'm doing, i tried looking up for some tutorials but its pretty hard and confusing to create my own points, I have bunch of icons from Illustrator to export but it seems exporting it gave me something like fill not a simple point to point line.
Is the exported SVG possible to do the animation above? If so, can anyone help me with a CSS snipit or if the SVG needs to be edited in some way, so i can have a base to learn? Thanks!
You can use the animate on each of the paths of the start:
svg {
width: 200px;
padding: 5px;
}
#star{
fill-opacity: 0;
stroke: #37475B;
stroke-width: 1;
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<g id="star">
<path id="star-1" class="st0" d="M37.9,27.9L49.3,5c0.3-0.6,0.8-0.6,1.1,0l11.3,22.9c0.3,0.6,1.1,0.9,1.7,0.7
c0.7-0.2,0.9-0.8,0.6-1.5L52,2.7c-0.5-1-1.3-1.6-2.2-1.6c-0.9,0-1.7,0.6-2.2,1.6L35.9,26.6c-0.3,0.6-0.1,1.4,0.5,1.7
C36.9,28.7,37.6,28.5,37.9,27.9z"/>
<path id="star-2" class="st0" d="M71.3,31.8c-0.7-0.1-1.2,0.1-1.3,0.5c0,0.2-0.1,0.4-0.1,0.6c-0.2,0.7,0.1,1.2,0.7,1.3l26.2,3.8
L77.9,56.7c-0.5,0.5-0.4,1.1,0.1,1.6c0.5,0.5,1.1,0.7,1.6,0.2l19.1-18.6c0.8-0.8,1.1-1.8,0.9-2.6c-0.3-0.9-1.1-1.4-2.2-1.6
L71.3,31.8z"/>
<path id="star-3" class="st0" d="M76.9,66.8c-0.1-0.7-0.8-1.2-1.4-1.1c0,0,0,0,0,0c-0.7,0.1-1.1,0.7-1,1.4l4.5,26.3L55.4,81.1
c-0.6-0.3-1.4-0.1-1.6,0.6c0,0,0,0,0,0c-0.3,0.6,0,1.4,0.6,1.7l23.4,12.3c0.5,0.3,1,0.4,1.5,0.4c0.7,0,1.2-0.3,1.6-0.7
c0.3-0.4,0.7-1.1,0.5-2.3L76.9,66.8z"/>
<path id="star-4" class="st0" d="M44.7,80.9l-24,12.6l4.5-26.3c0.1-0.7-0.3-1.3-1-1.5c0,0,0,0,0,0c-0.7-0.1-1.3,0.3-1.4,1
l-4.5,26.4c-0.2,1.2,0.2,1.9,0.5,2.3c0.7,0.8,1.9,1,3.1,0.3l23.7-12.5c0.6-0.3,1-1.1,0.7-1.7c0,0,0-0.1,0-0.1
C46,80.7,45.3,80.5,44.7,80.9z"/>
<path id="star-5" class="st0" d="M21.9,56.8L2.7,38.1l26.5-3.8c0.7-0.1,1.2-0.7,1-1.4c-0.2-0.6-0.8-1.1-1.5-1L2.3,35.6
c-1.1,0.2-1.9,0.8-2.2,1.6c-0.3,0.9,0,1.8,0.9,2.6l19.4,18.9c0.5,0.5,1.2,0.4,1.7-0.1c0,0,0,0,0,0C22.5,58.1,22.4,57.3,21.9,56.8z
"/>
</g>
<animate xlink:href="#star-1" attributeName="stroke-dashoffset" from="1000" to="0" dur="10s" fill="freeze" d="star-1-anim" />
<animate xlink:href="#star-2" attributeName="stroke-dashoffset" from="1000" to="0" dur="10s" fill="freeze" d="star-2-anim" begin="+1.5s"/>
<animate xlink:href="#star-3" attributeName="stroke-dashoffset" from="1000" to="0" dur="10s" fill="freeze" d="star-3-anim" begin="+3s"/>
<animate xlink:href="#star-4" attributeName="stroke-dashoffset" from="1000" to="0" dur="10s" fill="freeze" d="star-4-anim" begin="+4.5s"/>
<animate xlink:href="#star-5" attributeName="stroke-dashoffset" from="1000" to="0" dur="10s" fill="freeze" d="star-5-anim" begin="+6s"/>
</svg>
Hope it's what you were looking for.
You will have to fix a couple of things if you want this to work.
Firstly for the CSS line animation trick to work, you will need to change your triangle shapes to use a single stroke (ie. two lines) instead of an outline around the outside. See my answer on this other question for an explanation of that.
Secondly, you've got five separate shapes. If you want them to animate in sequence, one after the other, then you will have to time the animations. The animations for paths 2-5 will need to have a delay applied. You can do that with the animation-delay rule.
Demo
#star path {
fill: none;
stroke: #37475B;
stroke-width: 1;
stroke-dasharray: 190;
stroke-dashoffset: 190;
animation-name: draw-star;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
#keyframes draw-star {
to {
stroke-dashoffset: 0;
}
}
#star-2 {
animation-delay: 2s;
}
#star-3 {
animation-delay: 4s;
}
#star-4 {
animation-delay: 6s;
}
<svg width="300px" height="300px">
<g id="star">
<path id="star-1" d="M 100,90 L150,10 L 200,90" />
<path id="star-2" d="M 210,100 L 290,150 L 210,200" />
<path id="star-3" d="M 200,210 L150,290 L 100,210" />
<path id="star-4" d="M 90,200 L 10,150 L 90,100" />
</g>
</svg>