问题
Here trying to get some insight into SVGs. Is there any way of moving a circle along an SVG path, where the circle starts moving from a specific point determined by the length of the path?
For instance, when the object reaches the end, it starts again from the beginning. What attributes to use to get the circle to move from a random point, for example, starting from 20
not 0 to 100
?
There is a direct from and to in SVG, but I am not certain how to use it properly. Also, I found keytimes
to be useful in some cases, but it did not produce the desired result.
Here you can see the HTML of an SVG moving along a path, where it currently starts from the beginning:
<div id="pathContainer4">
<svg height="160" width="360">
<g fill="none" stroke="black" stroke-width="1">
<path stroke-dasharray="3" id="motionpath2"
d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" />
</g>
<circle class="circle2" r=8 fill=red ;z-index=55>
<animateMotion dur="2s" repeatCount="indefinite"
rotate="auto" from="20" to="100">
<mpath href="#motionpath2" />
</animateMotion>
</circle>
</svg>
</div>
回答1:
There is a direct from and to in SVG, but I am not certain how to use it properly. Also, I found keytimes to be useful in some cases, but it did not produce the desired result.
It is possible to start SVG animation without using JS from any point on the path, but its position must be determined in advance in the code.
A pair of attributes is used for this.
keyPoints="0;1" - movement from start to finish
keyTimes="0;1"
keyPoints="0.5;1" - movement from the middle of the way to the end
keyTimes="0;1"
keyPoints="1;0" - movement from end to start
keyTimes="0;1"
This way you can control the position of the starting point of the animation, but it is theoretically impossible to create an animation from a randomly selected point, since there are no variables in SVG, no arrays, no instructions for storing and executing mathematical functions.
In the example below, JS is used only to handle the event of pressing the control buttons:
<div id="pathContainer4">
<button id="btn1" onclick="forwardSVG()">forward</button />
<button id="btn2" onclick="middleSVG()">Middle</button />
<button id="btn3" onclick="backSVG()">Back</button />
</div>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" height="160" width="360" >
<g fill="none" stroke="black" stroke-width="1">
<path stroke-dasharray="3" id="motionpath2"
d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" />
</g>
<circle class="circle2" r=8 fill=red>
<animateMotion
id="forward"
dur="2s"
begin="indefinite"
repeatCount="1"
keyPoints="0;1"
keyTimes="0;1"
calcMode="linear" >
<mpath href="#motionpath2" />
</animateMotion>
<animateMotion
id="middle"
dur="2s"
begin="indefinite"
repeatCount="1"
keyPoints="0.5;1"
keyTimes="0;1"
calcMode="linear" >
<mpath href="#motionpath2" />
</animateMotion>
<animateMotion
id="back"
dur="2s"
begin="indefinite"
repeatCount="1"
keyPoints="1;0"
keyTimes="0;1"
calcMode="linear" >
<mpath href="#motionpath2" />
</animateMotion>
</circle>
</svg>
<script>
var animation1 = document.getElementById("forward")
function forwardSVG(){
animation1.beginElement();
}
var animation2 = document.getElementById("middle")
function middleSVG(){
animation2.beginElement();
}
var animation3 = document.getElementById("back")
function backSVG(){
animation3.beginElement();
}
</script>
Here are some examples of the illusion of chaotic letter movement without JS
<style>
#text1 {
fill:#B2000C;
}
</style>
<svg width="50%" height="50%" viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="tiny"
xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMinYMin meet">
<title>Animation of text x and y attributes</title>
<defs>
<linearGradient id="grad"
x1="0" y1="0" x2="0" y2="100%"
gradientUnits="userSpaceOnUse">
<stop offset="2%" stop-color="steelblue" />
<stop offset="45%" stop-color="hsla(180, 100%, 50%, 0)" />
<stop offset="45%" stop-color="hsla(80, 100%, 50%, 0)" />
<stop offset="95%" stop-color="yellowgreen" />
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#grad)" />
<text x="200 " y="500"
font-size="90" fill="#E4E4E4" stroke-width="4" stroke="#E4E4E4">Stackoverflow</text>
<text id="text1" x="200" y="500"
font-size="90">Stackoverflow</text>
<animate xlink:href="#text1"
attributeName="x"
attributeType="XML"
values="200 233 266 299 332 365 400 431 464 497 530 563 596;
100 600 200 365 700 465 465 563 530 398 431 850 900;
200 500 900 950 150 531 300 620 150 266 365 650 900;
332 233 820 300 800 633 200 670 300 850 800 530 266;
464 900 900 900 820 670 430 900 530 600 233 365 100;
332 100 100 100 500 100 800 563 900 700 900 100 100;
200 233 266 299 332 365 400 431 464 497 530 563 596"
dur="4s"
begin="0s"
repeatCount="2" />
<animate xlink:href="#text1"
attributeName="y"
attributeType="XML"
values="500 500 500 500 500 500 500 500 500 500 500 500 500;
100 200 850 100 250 175 750 100 750 720 850 500 50;
100 600 600 250 200 450 50 200 520 550 300 300 750;
500 100 650 650 600 150 550 50 150 550 200 550 400;
800 300 100 750 150 650 75 350 550 700 755 120 800;
800 600 300 150 750 350 700 650 200 250 500 650 100;
500 500 500 500 500 500 500 500 500 500 500 500 500"
dur="4s"
begin="0s"
repeatCount="2" />
</svg>
Vertical Parking Letters
<style>
#text1 {
fill:#B2000C;
}
</style>
<svg width="70%" height="70%" viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="tiny"
xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMinYMin meet">
<title>Animation of text x and y attributes</title>
<defs>
<linearGradient id="grad"
x1="0" y1="0" x2="0" y2="100%"
gradientUnits="userSpaceOnUse">
<stop offset="2%" stop-color="steelblue" />
<stop offset="45%" stop-color="hsla(180, 100%, 50%, 0)" />
<stop offset="45%" stop-color="hsla(80, 100%, 50%, 0)" />
<stop offset="95%" stop-color="yellowgreen" />
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#grad)" />
<text x="200 " y="500"
font-size="90" fill="#E4E4E4" stroke-width="4" stroke="#E4E4E4">Stackoverflow</text>
<text id="text1" x="200" y="500"
font-size="90">Stackoverflow</text>
<animate xlink:href="#text1"
attributeName="x"
attributeType="XML"
values="200 233 266 299 332 365 400 431 464 497 530 563 596;
100 600 200 365 700 465 465 563 530 398 431 850 900;
200 500 900 950 150 531 300 620 150 266 365 650 900;
332 233 820 300 800 633 200 670 300 850 800 530 266;
464 900 900 900 820 670 430 900 530 600 233 365 100;
332 100 100 100 500 100 800 563 900 700 900 100 100;
200 233 266 299 332 365 400 431 464 497 530 563 596"
dur="3s"
begin="0s"
repeatCount="2" />
<animate xlink:href="#text1"
attributeName="y"
attributeType="XML"
values="500 500 500 500 500 500 500 500 500 500 500 500 500;
100 200 850 100 250 175 750 100 750 720 850 500 50;
100 600 600 250 200 450 50 200 520 550 300 300 750;
500 100 650 650 600 150 550 50 150 550 200 550 400;
800 300 100 750 150 650 75 350 550 700 755 120 800;
800 600 300 150 750 350 700 650 200 250 500 650 100;
500 500 500 500 500 500 500 500 500 500 500 500 500"
dur="4s"
begin="0s"
repeatCount="2" />
</svg>
Horizontal Parking Letters
<style>
#text1 {
fill:#B2000C;
}
</style>
<svg width="50%" height="50%" viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="tiny"
xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMinYMin meet">
<title>Animation of text x and y attributes</title>
<defs>
<linearGradient id="grad"
x1="0" y1="0" x2="0" y2="100%"
gradientUnits="userSpaceOnUse">
<stop offset="2%" stop-color="steelblue" />
<stop offset="45%" stop-color="hsla(180, 100%, 50%, 0)" />
<stop offset="45%" stop-color="hsla(80, 100%, 50%, 0)" />
<stop offset="95%" stop-color="yellowgreen" />
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#grad)" />
<text x="200 " y="500"
font-size="90" fill="#E4E4E4" stroke-width="4" stroke="#E4E4E4">Stackoverflow</text>
<text id="text1" x="200" y="500"
font-size="90">Stackoverflow</text>
<animate xlink:href="#text1"
attributeName="x"
attributeType="XML"
values="200 233 266 299 332 365 400 431 464 497 530 563 596;
100 600 200 365 700 465 465 563 530 398 431 850 900;
200 500 900 950 150 531 300 620 150 266 365 650 900;
332 233 820 300 800 633 200 670 300 850 800 530 266;
464 900 900 900 820 670 430 900 530 600 233 365 100;
332 100 100 100 500 100 800 563 900 700 900 100 100;
200 233 266 299 332 365 400 431 464 497 530 563 596"
dur="4s"
begin="0s"
repeatCount="2" />
<animate xlink:href="#text1"
attributeName="y"
attributeType="XML"
values="500 500 500 500 500 500 500 500 500 500 500 500 500;
100 200 850 100 250 175 750 100 750 720 850 500 50;
100 600 600 250 200 450 50 200 520 550 300 300 750;
500 100 650 650 600 150 550 50 150 550 200 550 400;
800 300 100 750 150 650 75 350 550 700 755 120 800;
800 600 300 150 750 350 700 650 200 250 500 650 100;
500 500 500 500 500 500 500 500 500 500 500 500 500"
dur="3s"
begin="0s"
repeatCount="2" />
</svg>
Another example of the illusion of random movement of billiard balls
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" height="100vh" viewBox="0 0 400 400">
<rect width="100%" height="100%" rx="25" fill="green" stroke="#9D8500" stroke-width="15"/>
<circle cx="50%" cy="20%" r="3%" fill="url(#gradB)" >
<animate attributeName="cx" dur="3" values="3%;97%;3%"
repeatCount="indefinite" />
<animate attributeName="cy" dur="2.8" values="3%;97%;3%"
repeatCount="indefinite" />
</circle>
<circle cx="30%" cy="70%" r="3%" fill="url(#gradR)" >
<animate attributeName="cx" dur="2.7" values="97%;3%;97%"
repeatCount="indefinite" />
<animate attributeName="cy" dur="3.1" values="3%;97%;3%"
repeatCount="indefinite" />
</circle>
<radialGradient id="gradB" cx="20%" cy="20%" r="100%" fx="30%" fy="30%">
<stop stop-color="white" offset="0"/>
<stop stop-color="blue" offset="25%"/>
<stop stop-color="rgb(0,0,192)" offset="50%"/>
<stop stop-color="rgb(0,0,127)" offset="70%"/>
<stop stop-color="rgb(0,0,64)" offset="85%"/>
<stop stop-color="rgb(0,0,0)" offset="100%"/>
</radialGradient>
<radialGradient id="gradR" cx="20%" cy="20%" r="100%" fx="30%" fy="30%">
<stop stop-color="white" offset="0"/>
<stop stop-color="red" offset="25%"/>
<stop stop-color="rgb(192,0,0)" offset="50%"/>
<stop stop-color="rgb(127,0,0)" offset="70%"/>
<stop stop-color="rgb(64,0,0)" offset="85%"/>
<stop stop-color="rgb(0,0,0)" offset="100%"/>
</radialGradient>
</svg>
来源:https://stackoverflow.com/questions/59291368/starting-an-object-to-move-from-a-random-point-along-an-svg-path