SVG animateTransform 缩放 keySplines 以匹配旋转矢量的 Y 分量
SVG animateTransform scaling keySplines to match Y component of rotating vector
我需要模拟二维旋转箭头。它必须跟上旋转的蓝色箭头。
我从红色箭头所示的 keySplines 开始,当使用
http://franzheidl.github.io/keysplines/
但是和旋转矢量不太匹配
我试错了很多次,到目前为止我最好的结果显示为绿色,但它仍然与旋转箭头不匹配。
<!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>
有人对如何设置 keySplines 以获得期望的结果有任何见解吗?
除了使用 SMIL,您还需要使用其他类型的动画来计算箭头尖端的 y 值。由于您围绕点 {0,0} 进行了旋转,因此 y = 100 * Math.sin(rad) 其中 100 是箭头的长度,rad 是以弧度为单位的旋转角度。
在这种情况下,比例的值将为 y/100。此外,您还需要考虑箭头的初始角度 (-90)
在下一个示例中,我将使用 javascript 进行计算:
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>
我需要模拟二维旋转箭头。它必须跟上旋转的蓝色箭头。
我从红色箭头所示的 keySplines 开始,当使用 http://franzheidl.github.io/keysplines/
但是和旋转矢量不太匹配
我试错了很多次,到目前为止我最好的结果显示为绿色,但它仍然与旋转箭头不匹配。
<!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>
有人对如何设置 keySplines 以获得期望的结果有任何见解吗?
除了使用 SMIL,您还需要使用其他类型的动画来计算箭头尖端的 y 值。由于您围绕点 {0,0} 进行了旋转,因此 y = 100 * Math.sin(rad) 其中 100 是箭头的长度,rad 是以弧度为单位的旋转角度。
在这种情况下,比例的值将为 y/100。此外,您还需要考虑箭头的初始角度 (-90)
在下一个示例中,我将使用 javascript 进行计算:
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>