SVG animateTransform 缩放 keySplines 以匹配旋转向量的 Y 分量

标签 svg scale spline cubic-spline animatetransform

我需要模拟二维旋转箭头。它必须与旋转的蓝色箭头保持同步。

我从红色箭头所示的 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>

关于SVG animateTransform 缩放 keySplines 以匹配旋转向量的 Y 分量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71904306/

相关文章:

android - 如何在 android webview 中禁用双击缩放?

ios - 人脸检测 ios7 坐标缩放问题

matlab - 如何在 MATLAB 中实现分段函数,然后按特定间隔绘制它

c# - 平滑手绘曲线

javascript - 具有多个系列的 highcharts 样条线每隔几秒更新一次

javascript - 为什么更新 d3.js 强制布局时必须重新分配链接和节点

html - SVG 简单动画

svg - 在路径末尾重置简单的 svg 对象

javascript - 没有使用 webpack 加载的 React 图标

css 动画比例不起作用