【问题标题】:SVG animate a bezier curve to grow by following an arrowheadSVG 动画一条贝塞尔曲线以跟随箭头增长
【发布时间】:2020-12-10 17:40:49
【问题描述】:

我正在尝试创建一个箭头,其箭头从起点移动并在其目标处结束。使用@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>

【问题讨论】:

    标签: animation svg bezier curve arrows


    【解决方案1】:

    我猜是这样的。请注意,您也可以在 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>

    【讨论】:

    • 嗨@Robert 感谢您的快速回复,非常感谢。我喜欢这个结果,但想知道您是如何得出 stroke-dasharray 和 stroke-dashoffset 的数字 118.27912902832031 的?我想知道如何计算它,因为许多这样的箭头将以编程方式即时创建。使用 SMIL 可以更轻松、更好地完成这项工作吗?
    • 嗨罗伯特,请忽略我之前的评论。非常感谢你的帮助。在不计算总长度的情况下,使用 SMIL 可以做得更好吗?请告诉我。
    • 你仍然需要知道总长度。
    【解决方案2】:

    同时移动光标和行:

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

    最大曲线长度为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> 

    【讨论】:

    • @Velusamy Velu 添加几行 JS 显示控制台中的最大行长
    • @Alexander_TT - 感谢您的帮助。谢谢你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    相关资源
    最近更新 更多