I am not very familiar in working with SVG and am trying to animate a <path> line:
The following is what I am trying to achieve
The orange circle at the end should run along the blue line, however I cannot figure out how to get the loop at the end of the line (the red block in the middle can be ignored, it is a custom icon).
so far I have the following:
<svg width="192" height="160" xmlns="http://www.w3.org/2000/svg">
<circle class="circle" cx="0" cy=0 r=7 stroke=#f70202 stroke-width=2 fill=#f92020 >
<animateMotion dur="1s" repeatCount="indefinite" rotate="auto" >
<mpath xlink:href="#path"/>
</animateMotion>
</circle>
<path id="path" d="M10 50 Q 95 150 180 120" stroke="red" stroke-width="2" fill="none"/>
</svg>
Here is codepen for the same: https://codepen.io/undert0w/pen/jOVVJMe
How can I extend the blue line with a loop and have the orange circle follow the blue line?
(ps. I am using Angular if it makes any difference)
<svg width="600" height="800" xmlns="http://www.w3.org/2000/svg">
<circle class="circle" cx="0" cy=0 r=7 stroke=#f70202 stroke-width=2 fill=#f92020 >
<animateMotion dur="5s" repeatCount="indefinite" rotate="auto" >
<mpath xlink:href="#path"/>
</animateMotion>
</circle>
<path id="path" d="M61,50c0,0,76,143,163,103S288-1,411,50s180,90,113,165s-203-16-207-53s163-99,154-30c0,0-14,55-30,55
s-33.5-6.7-76-23s-29-87.1-76-23.6S224,229,177,213s-91,2-59-64s27-87,68-91s9,35,82,36s55,14,112-20S480-35,528,31s38,106,5,127
s-43,50-27,62s45,19,45,19" stroke="red" stroke-width="2" fill="none"/>
</svg>
The easiest way is to draw the line you want in Illustrator, then save it as SVG
after that just click: SVG Code and take the code of path between d="...."
!!Remember!! to adjust the viewBox area
Here is a code that's done this way.
<svg width="600" height="800" xmlns="http://www.w3.org/2000/svg">
<circle class="circle" cx="0" cy=0 r=7 stroke=#f70202 stroke-width=2 fill=#f92020 >
<animateMotion dur="1s" repeatCount="indefinite" rotate="auto" >
<mpath xlink:href="#path"/>
</animateMotion>
</circle>
<path id="path" d="M61,50c0,0,76,143,163,103S288-1,411,50s180,90,113,165s-203-16-207-53s163-99,154-30" stroke="red" stroke-width="2" fill="none"/>
</svg>
Not sure if I got the question right. But if you are trying to create a loop path with the blue line.
Try creating the path in any svg editor and copy the source.
You can understand clearly from this recording.
https://youtu.be/vjLCAMaBr4A
Related
I am having a situation which is very very much like this one:
How to position an SVG circle along another circle's path
Actually it is almost identical, except I am not working with a circle, I am working with a div which contains an image, but the div does not show at all, not even in the browser's inspector.
So referencing the same solution to the other question, this is what he got:
<div style="width:400px">
<svg viewBox="0 -10 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="50 85"></path>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</circle>
</svg>
</div>
It works perfectly fine, now my situation is the same, except I am trying to have a a div and img instead of a circle, and although it should work in theory but it does not show the div:
<div style="width:400px">
<svg viewBox="0 -10 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="50 85"></path>
<!-- make animateMotion a child of the div , no need to use xlink:href,
just like it is done in the answer above -->
<div>
<img src="http://placekitten.com/200/300"/>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</div>
</svg>
</div>
Or a better way by referencing the object ID:
<div style="width:400px">
<svg viewBox="0 -10 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="50 85"></path>
<div id="my-circle">
<img src="http://placekitten.com/200/300"/>
</div>
<!-- keep animateMotion out side of the div and use xlink:href-->
<animateMotion
xlink:href="#my-circle"
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</svg>
</div>
However you can see in both cases, the div is not showing, any reason for this?
Thank you
I'm trying to show parts of an image with a fade in animation. So this is what I've done:
I created an SVG with 2 paths (2 parts of the image that I want to show with a fade in animation)
I clipped the SVG to the image
The result is: the image has a mask and only those 2 parts are shown.
Everything's good but now I have to animate them and I cannot find enything that help me. Can you?
This is my code
<style>
img {
clip-path: url(#clip);
width: 100%;
}
</style>
<img src="https://wikitesti.com/wp-content/uploads/2020/11/yellow-is-the-color-of.jpg"/>
<svg xmlns="http://www.w3.org/2000/svg"
width="3.33333in" height="2.5in"
viewBox="0 0 1000 750">
<clipPath id="clip" clipPathUnits="objectBoundingBox" transform="scale(0.001, 0.0013333333333333)">
<path id="path" d="M 416.00,140.00
C 426.58,139.14 423.70,137.74 438.00,138.00
440.13,138.04 442.65,137.95 444.26,139.60
446.32,141.71 446.00,146.23 446.00,149.00
446.00,149.00 446.00,175.00 446.00,175.00
446.00,175.00 452.00,230.00 452.00,230.00
452.00,230.00 452.00,242.00 452.00,242.00
452.00,242.00 454.66,271.00 454.66,271.00
454.66,271.00 454.09,277.00 454.09,277.00
454.09,277.00 458.25,312.00 458.25,312.00
459.85,321.79 462.98,335.77 463.00,345.00
463.00,345.00 465.00,372.00 465.00,372.00
465.02,385.91 468.58,409.91 462.00,422.00
462.00,422.00 435.08,408.00 435.08,408.00
435.08,408.00 435.08,397.00 435.08,397.00
435.08,397.00 436.82,381.00 436.82,381.00
436.82,381.00 433.17,360.00 433.17,360.00
433.17,360.00 431.48,338.00 431.48,338.00
431.48,338.00 424.17,308.00 424.17,308.00
424.17,308.00 424.95,294.00 424.95,294.00
424.95,294.00 424.95,283.00 424.95,283.00
424.95,283.00 424.09,273.00 424.09,273.00
424.09,273.00 421.91,239.00 421.91,239.00
421.91,239.00 421.00,227.00 421.00,227.00
421.00,227.00 421.00,202.00 421.00,202.00
421.00,202.00 420.00,190.00 420.00,190.00
420.00,190.00 420.00,179.00 420.00,179.00
420.00,179.00 419.00,165.00 419.00,165.00
419.00,165.00 417.79,148.00 417.79,148.00
417.79,148.00 416.00,140.00 416.00,140.00 Z" fill="#C4C4C4"/>
<path class="fade-in three" id="path2" d="M 530.00,168.00
C 530.00,168.00 588.00,168.00 588.00,168.00
588.00,168.00 588.00,468.00 588.00,468.00
588.00,468.00 530.00,468.00 530.00,468.00
530.00,468.00 530.00,168.00 530.00,168.00 Z" fill="#C4C4C4" />
</clipPath>
</svg>
Thank you.
[EDIT]
I tried to do something like this:
<path....>
<animate attributeType="CSS" attributeName="opacity" from="1" to="0" dur="5s" repeatCount="indefinite" />
</path>
But it seems like if path is clipped opacity doesn't work
[EDIT]
I have to animate them with different duration and delay so I cannot just animate the image
[DESIRED RESULT]
This should be the final results. Same picture, different masks and different fade in effect time
SOLVED!!!
Solution is not clipping the path to the image but setting the image as path background and then animate the path.
Here is the code:
<svg xmlns="http://www.w3.org/2000/svg"
width="50%" height="50%"
viewBox="0 0 1000 750">
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="1000" height="750">
<image href="image_to_mask.jpg" x="0" y="0" width="1000" height="750" />
</pattern>
</defs>
<path id="path1" opacity="0" d="M 296.00,277.00
C 296.00,277.00 699.00,277.00 699.00,277.00
699.00,277.00 699.00,353.00 699.00,353.00
699.00,353.00 296.00,353.00 296.00,353.00
296.00,353.00 296.00,277.00 296.00,277.00 Z" fill="url(#img1)">
<animate attributeType="CSS" attributeName="opacity" from="0" to="1" dur="0.5s" fill="freeze"/>
</path>
<path id="path2" opacity="0" d="M 222.00,466.00
C 222.00,466.00 792.00,466.00 792.00,466.00
792.00,466.00 792.00,580.00 792.00,580.00
792.00,580.00 222.00,580.00 222.00,580.00
222.00,580.00 222.00,466.00 222.00,466.00 Z" fill="url(#img1)">
<animate attributeType="CSS" attributeName="opacity" from="0" to="1" dur="0.5s" begin="0.5s" fill="freeze"/>
</path>
</svg>
I have a repeating 20-second svg animation. Halfway (10 seconds) it should abruptly hide one path-element called leftside. When the animation finishes and repeats, it should show the element again. How can I achieve this?
Right now, I got the first loop working. But the reset when the animation repeats isn't working unfortunately.
This is what I have:
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<animateMotion id="movement"
xlink:href="#vehicle"
dur="20s"
begin="0;movement.end+4s"
fill="freeze"
keyPoints="0;1;0"
keyTimes="0;0.5;1"
calcMode="spline"
keySplines= ".6 .01 .2 1; 0.6 .01 .2 1";
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<animate xlink:href="#leftside" attributeName="opacity" from="1" to="0" dur="0.01s" begin="10s;movement.begin+10s;" repeatCount="indefinitive" fill="freeze" />
<animate xlink:href="#leftside" attributeName="opacity" from="0" to="1" dur="0.01s" begin="movement.begin" repeatCount="indefinitive" fill="freeze" />
</svg>
Mybe so?
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle" stroke-width="2" stroke="red">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<!-- Two dash move forward 10s -->
<animateMotion id="movement_forward"
xlink:href="#vehicle"
dur="10s"
begin="0;movement_back.end"
keyPoints="0;1"
keyTimes="0;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<!-- One dash goes back 10 seconds -->
<animateMotion id="movement_back"
xlink:href="#rightside"
dur="10s"
begin="movement_forward.end"
keyPoints="1;0"
keyTimes="0;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>
begin="0;movement_back.end" - the restart of the first animation starts after the end of the second animation
begin="movement_forward.end - thus, two animations loop. When the first animation ends, the second animation begins
For uneven movement on different sections of the path, you need to change the attribute values:
keyPoints="0;0.2;0.4;0.8;1"
keyTimes="0;0.495;0.6;0.75;1"
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle" stroke-width="2" stroke="red">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<!-- Two dash move forward 10s -->
<animateMotion id="movement_forward"
xlink:href="#vehicle"
dur="10s"
begin="0;movement_back.end"
keyPoints="0;0.2;0.4;0.8;1"
keyTimes="0;0.495;0.6;0.75;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<!-- One dash goes back 10 seconds -->
<animateMotion id="movement_back"
xlink:href="#rightside"
dur="10s"
begin="movement_forward.end"
keyPoints="1;0.8;0.4;0.2;0"
keyTimes="0;0.495;0.6;0.75;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>
This is hard to follow for me, but I got this solution:
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<animateMotion id="movement"
xlink:href="#vehicle"
dur="20s"
begin="0;movement.end+4s"
fill="freeze"
keyPoints="0;1;0"
keyTimes="0;0.5;1"
calcMode="spline"
keySplines= ".6 .01 .2 1; 0.6 .01 .2 1";
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<animate xlink:href="#leftside" attributeName="opacity" from="1" to="0" dur="0.01s" begin="movement.begin+10s; 20s" fill="freeze" />
<animate xlink:href="#leftside" attributeName="opacity" from="0" to="1" dur="0.01s" begin="movement.begin" fill="freeze" />
</svg>
A couple of points:
If you want to repeat the animation, the keyword is indefinite, not indefinitive.
You apparently wanted to set the leftside animation to indefinite. This would apply to the opacity animation itself, with a 0.01s duration. This means that, after being triggered, the animation would be repeating itself every 0.01s in a blinking pattern.
I believe the issue here is related to the interplay between both leftside animations, and which one has the preference at each time. However, it looks like a complex issue, and I do not understand it fully (explained here).
I've come up with this SVG image.
<svg width="250px" height="250px" viewBox="0 0 250 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<def>
</def>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group">
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100">
</circle>
<circle id="Oval" fill="#228B22" fill-rule="nonzero" cx="171" cy="31" r="16">
</circle>
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>
Fiddle here: http://jsfiddle.net/9zkfodwp/1377/
Now, I wanted an image inside the circle. So, I tried to use a clip-path1 and the code is below: But, that image doesn't appear here.
<svg width="250px" height="250px" viewBox="0 0 250 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<def>
<clipPath id="myCircle">
<circle id="Oval" fill="#228B22" fill-rule="nonzero" cx="171" cy="31" r="16">
</circle>
</clipPath>
</def>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group">
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100">
</circle>
<image width="50" height="35" xlink:href="https://www.tutorialspoint.com/videotutorials/images/coding_ground_home.jpg" clip-path="url(#myCircle)" />
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>
Fiddle here: http://jsfiddle.net/9zkfodwp/1380/
My questions are:
Chrome doesn't display the image as in the above fiddle though.
The one in the fiddle - doesn't actually fit in to a circle. The image is in a square shape.
(The book image is in rectangle shape - shouldn't be it inside the circle ? As we are filling the circle with the image ?
Any ideas on what should be done on this regard will be appreciated.
There are a couple of things wrong with your fiddle:
It is <defs>, not <def>. That whole section was being ignored.
Your image and the clip path circle were in different places. They didn't overlap with one another. I've updated the <image> to be centred over the clip path circle.
<svg width="250px" height="250px" viewBox="0 0 250 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="myCircle">
<circle id="Oval" cx="171" cy="31" r="16"/>
</clipPath>
</defs>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group">
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100"/>
<image x="146" y="14" width="50" height="35"
xlink:href="https://www.tutorialspoint.com/videotutorials/images/coding_ground_home.jpg"
clip-path="url(#myCircle)" />
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>
Is this what you're tying to do.
you need to flip the image on the x-y axis, you can do that by adding scale it and add transformation.
check this code:
<svg width="350px" height="350px" viewBox="0 0 350 350" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<def>
<clipPath id="myCircle">
<circle id="Oval" fill="#228B22" fill-rule="nonzero" cx="171" cy="31" r="16">
</circle>
</clipPath>
</def>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group" >
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100">
</circle>
<image width="50" height="35" xlink:href="https://www.tutorialspoint.com/videotutorials/images/coding_ground_home.jpg" clip-path="url(#myCircle)" transform="scale (-1, 1) translate(-60, 45)" />
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>
I need to make the note traverse along the path that is drawn, i found a way in by translating the path to the starting position of the note. But is there a workaround by which I can keep the position of the path fixed yet make the note traverse along the path.
My code
<svg width="900" height="900" viewBox="0 0 900 900" xmlns:xlink="http://www.w3.org/1999/xlink">
<g >
<path id="motion" fill="none" stroke="#000000" stroke-miterlimit="10" class="st0" d="M0,306c0,0,155-108.6,313.8-65.3s123.7,101,256.7,105.2S733.1,191.2,792,188.2" />
</g>
<g id="car" transform="translate(-100,150)">
<path id="note" fill="red"transform="scale(.5,.5)" transform="translate(0,0)" d="M248.8,306.8c0,0-24-7-28.5,11c0,0-3,16,21,16.5c0,0,19.5,2.3,18.5-28.8s0-61.2,0-61.2s42,9,19,31.5c0,0,17-1,13.5-23c0,0-7.5-20-43-22L248.8,306.8z" />
</g>
<animateMotion xlink:href="#car" dur="5s" begin="click" fill="freeze" repeatCount="indefinite" origin="(0,6)">
<mpath xlink:href="#motion" />
</animateMotion>
</svg>
JSFiddle example