SVG 动画贝塞尔曲线跟随箭头增长

SVG animate a bezier curve to grow by following an arrowhead

我正在尝试创建一个箭头,其箭头从起点移动到目标。使用@Robert Longson 的提示成功移动箭头。我希望轴的末端也跟随箭头并长到它的全长。下面给出了代码,请注意轴没有随箭头一起增长,并且也以部分长度结束。有没有办法纠正这个问题。任何帮助将不胜感激。

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="5 0 100 45">
    <style>
        .wire {
            fill: none;
            stroke: red;
            stroke-width: 1px;

            /* Stroke-dasharray property to animate */
            stroke-dasharray: 100%;
            stroke-dashoffset: 100%;
            animation: move linear 5s;
        }

        @keyframes move {
            100% {
                stroke-dashoffset: 0;
            }
        }
    </style>
    <path d="M10,10 C15,50 95,50 100,10" stroke="blue" stroke-width="2" id="wire" class="wire">
        <animate>
            <mpath xlink:href="#wire" />
        </animate>
    </path>
    <!-- acceptable movement along the path but incorrect orientation -->
    <polygon points="-5,-5 5,0 -5,5 -3,0" fill="red">
        <animateMotion dur="5s" repeatCount="1" rotate="auto" fill="freeze">
            <mpath xlink:href="#wire" />
        </animateMotion>
    </polygon> 
</svg>

我猜是这样的。请注意,您也可以在 SMIL 中完成此操作。

我已经将动画设置为向前,所以它保持在最后,否则曲线会在动画结束时消失。

console.log 行显示我从哪里得到号码。

console.log(document.getElementsByTagName("path")[0].getTotalLength())
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="5 0 100 45">
    <style>
        .wire {
            fill: none;
            stroke: red;
            stroke-width: 1px;

            /* Stroke-dasharray property to animate */
            stroke-dasharray: 118.27912902832031;
            stroke-dashoffset: 118.27912902832031;
            animation: move linear 5s forwards;
        }

        @keyframes move {
            100% {
                stroke-dashoffset: 0;
            }
        }
    </style>
    <path d="M10,10 C15,50 95,50 100,10" stroke="blue" stroke-width="2" id="wire" class="wire">
        <animate>
            <mpath xlink:href="#wire" />
        </animate>
    </path>
    <!-- acceptable movement along the path but incorrect orientation -->
    <polygon points="-5,-5 5,0 -5,5 -3,0" fill="red">
        <animateMotion dur="5s" repeatCount="1" rotate="auto" fill="freeze">
            <mpath xlink:href="#wire" />
        </animateMotion>
    </polygon> 
</svg>

同时移动光标和行:

  1. 有必要在开始时间 begin="svg1.click" 和持续时间 dur="5s"
  2. 同步两个动画

最大曲线长度是118.3px所以

stroke-dashoffset:118.3px;
stroke-dasharray:118.3px;

#wire {
stroke-dashoffset:118.3px;
stroke-dasharray:118.3px;
stroke:red;
stroke-width:2px;
fill:none;
}
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="5 0 100 45">
    <style>
       
    </style>
    <path id="wire" d="M10,10 C15,50 95,50 100,10" >  
       <!-- Curved path growth animation -->
        <animate
           attributeName="stroke-dashoffset"
           begin="svg1.click"
           dur="5s"
           values="118.3;0"
           calcMode="linear"
           fill="freeze"
           restart="whenNotActive" /> 
        </animate>
    </path>
    <!-- Cursor -->
    <polygon points="-5,-5 5,0 -5,5 -3,0" fill="red">
          <!-- Animating cursor movement along a curved path -->
        <animateMotion begin="svg1.click" dur="5s" repeatCount="1" calcMode="linear" rotate="auto" fill="freeze">
            <mpath xlink:href="#wire" />
        </animateMotion>
    </polygon>  
    <text x="40" y="20" font-size="6px" fill="dodgerblue">Click me</text>
</svg>  
<script>
var path = document.querySelector('#wire');
        var len = (path.getTotalLength() );
        console.log("Path length - " + len);
</script>       

更新

作为奖励: 前进-后退

  • 要控制移动方向,请添加两个按钮和一个 onclick 事件
<div>
    <button onclick="forward.beginElement()">forward</button>
    <button onclick="back.beginElement()">back</button>
</div>  
  • 光标的方向由几个参数控制:
keyPoints="0;1"
keyTimes="0;1"
  • 线增长或下降的动画取决于值 stroke-dashoffset

values="118.3;0" - 线增长 values="0;118.3" - 减少线`

#wire {
stroke-dashoffset:118.3px;
stroke-dasharray:118.3px;
stroke:red;
stroke-width:2px;
fill:none;
}
svg {
width:50%;
height:50%;
}
<div>
    <button onclick="forward.beginElement()">forward</button>
    <button onclick="back.beginElement()">back</button>
</div>  
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="5 0 100 45">
    <style>
       
    </style>
    <path id="wire" d="M10,10 C15,50 95,50 100,10" >  
       <!-- Animation of filling, growing a line (`forward`)-->
        <animate id="strokeForward"
           attributeName="stroke-dashoffset"
           begin="forward.begin"
           dur="5s"
           values="118.3;0"
           calcMode="linear"
           
           fill="freeze"
           restart="whenNotActive" /> 
          <!-- String decrease animation (`back`) -->
       <animate id="strokeBack"
           attributeName="stroke-dashoffset"
           begin="back.begin"
           dur="5s"
           values="0;118.3"
           calcMode="linear"
           fill="freeze"
           restart="whenNotActive" /> 
       
    </path>
    <!-- Cursor -->
    <polygon points="-5,-5 5,0 -5,5 -3,0" fill="red">
          <!-- Animating cursor movement along a curved path (`forward`) -->
    <animateMotion
          id="forward"
          begin="indefinite"
          dur="5s"
          repeatCount="1"
          calcMode="linear"
          rotate="auto"
          fill="freeze"
          keyPoints="0;1"
          keyTimes="0;1"
          restart="whenNotActive">
            <mpath xlink:href="#wire" />
        </animateMotion>    
        <!-- Animating cursor movement along a curved path (`back`) -->
         <animateMotion
          id="back"
          begin="indefinite"
          dur="5s"
          repeatCount="1"
          calcMode="linear"
          rotate="auto"
          fill="freeze"
          keyPoints="1;0"
          keyTimes="0;1"
          restart="whenNotActive">
            <mpath xlink:href="#wire" />
        </animateMotion>  
    </polygon>  
    </svg>