I need to simulate a rotating arrow in 2D. It has to keep pace with the rotating blue arrow.
I started with keySplines shown by the red arrow that gave a nice quadrant when viewed using http://franzheidl.github.io/keysplines/
But it didn't match the rotating vector very well.
I've fudged numerous attempts and the best I've managed so far is shown in green but it still doesn't match the rotating arrow.
Anyone got any insights on how to set keySplines to get a desired result?
<!DOCTYPE html>
<body>
<svg width="800" height="400" viewBox="0 0 800 400" version="1.1" id="svg5">
<defs>
<g id="layer1a">
<path id="vect1a"
style="stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,0 h -10 v -80 h -10 l 20,-20 20,20 h -10 v 80 z" />
<animateTransform additive=sum attributeName="transform" type="rotate"
begin="0s" dur="12s"
from="0 0 0" to="360 0 0"
repeatCount="2.125" fill="freeze" />
</g>
<g id="line1">
<line x1="0" y1="0" x2="800" y2="0">
</g>
</defs>
<g id="layer3" transform="translate(0,200)">
<path
style="fill:#ffffff;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,0 h 800"
id="line"
/>
</g>
<use href="#layer1a" style="fill:#0000ff" transform="translate(150,200)" />
<use href="#line1" style="stroke:rgb(255,0,0);stroke-width:2" transform="translate(0,200)">
<animateTransform
additive="sum"
id="line1at0"
attributeName="transform"
type="translate"
calcMode="spline"
begin="0s"
dur="12s"
values="0 -100 ; 0 0 ; 0 100 ;0 0 ; 0 -100"
keyTimes="0 ; 0.25 ; 0.5 ; 0.75 ; 1"
keySplines="0.5 0 1 .5 ; 0 0.5 0.5 1 ; 0.5 0 1 .5 ; 0 0.5 0.5 1"
repeatCount="2.125"
fill="freeze" />
</use>
<use xlink:href="#vect1a" style="fill:#ff0000" transform="translate(300,200)" >
<animateTransform
additive="sum"
id="arrow1at0"
attributeName="transform"
type="scale"
calcMode="spline"
begin="0s"
dur="12s"
values="1 1 ; 1 0 ; 1 -1 ; 1 0 ; 1 1"
keyTimes="0 ; 0.25 ; 0.5 ; 0.75 ; 1"
keySplines="0.5 0 1 .5 ; 0 0.5 0.5 1 ; 0.5 0 1 .5 ; 0 0.5 0.5 1"
repeatCount="2.125"
fill="freeze" />
</use>
<use href="#line1" style="stroke:rgb(255,0,0);stroke-width:2" transform="translate(0,200)">
<animateTransform
additive="sum"
id="line1at0"
attributeName="transform"
type="translate"
calcMode="spline"
begin="0s"
dur="12s"
values="0 -100 ; 0 0 ; 0 100 ;0 0 ; 0 -100"
keyTimes="0 ; 0.25 ; 0.5 ; 0.75 ; 1"
keySplines="0.5 0 1 .5 ; 0 0.5 0.5 1 ; 0.5 0 1 .5 ; 0 0.5 0.5 1"
repeatCount="2.125"
fill="freeze" />
</use>
<use xlink:href="#vect1a" style="fill:#00ff00" transform="translate(450,200)" >
<animateTransform
additive="sum"
id="arrow1bt0"
attributeName="transform"
type="scale"
calcMode="spline"
begin="0s"
dur="12s"
values="1 1 ; 1 0 ; 1 -1 ; 1 0 ; 1 1"
keyTimes="0 ; 0.25 ; 0.5 ; 0.75 ; 1"
keySplines="1 .75 .25 0 ; 0 .25 .75 1 ; 1 .75 .25 0 ; 0 .25 .75 1"
repeatCount="2.125"
fill="freeze" />
</use>
<use href="#line1" style="stroke:rgb(0,255,0);stroke-width:2" transform="translate(0,200)">
<animateTransform
additive="sum"
id="line1bt0"
attributeName="transform"
type="translate"
calcMode="spline"
begin="0s"
dur="12s"
values="0 -100 ; 0 0 ; 0 100 ;0 0 ; 0 -100"
keyTimes="0 ; 0.25 ; 0.5 ; 0.75 ; 1"
keySplines="1 .75 .25 0 ; 0 .25 .75 1 ; 1 .75 .25 0 ; 0 .25 .75 1"
repeatCount="2.125"
fill="freeze" />
</use>
</svg>
</body>
</html>
CodePudding user response:
Instead of using SMIL you will need to use some other kind of animation that is allowing you to calculate the y value of the tip of the arrow. Since you have a rotation around point {0,0} the y = 100 * Math.sin(rad) where 100 is the length of the arrow and rad is the rotation angle in radians.
In this case the value for the scale will be y/100. Also you will need to account for the fact that the arrow has an initial angle (-90)
In the next example I'm using javascript for the calculation:
let a = 0;//the angle
function anim() {
a ;//increasing the angle with each frame
use1.setAttribute("transform", `rotate(${a})`);
let rad = (a 90) * (Math.PI / 180);//the angle in radians
use2.setAttribute("transform", `scale(1,${Math.sin(rad)})`);
use3.setAttribute("transform", `translate(0,${100 * Math.sin(-rad)})`);
window.requestAnimationFrame(anim);
}
window.requestAnimationFrame(anim);
<svg width="800" height="400" viewBox="-120 -101 800 400" version="1.1" id="svg5">
<defs>
<path id="vect1a" d="m 0,0 h -10 v -80 h -10 l 20,-20 20,20 h -10 v 80 z" />
</defs>
<line id="line" x1="-120" x2="800" stroke="black" />
<use id="use1" xlink:href="#vect1a" />
<g transform="translate(200,0)">
<use id="use2" xlink:href="#vect1a" />
</g>
<use id="use3" xlink:href="#line" />
</svg>