Search code examples
animationsvgbeziercurvearrows

SVG animate a bezier curve to grow by following an arrowhead


I'm trying to create an arrow with its arrowhead moving from a starting point and ending at its target. Moving the arrowhead was achieved successfully with the tip from @Robert Longson. I want the end of the shaft also to follow the arrowhead and grow to its full length. The code is given below and notice that the shaft isn't growing with the arrowhead and also ends up in partial length. Is there a way to correct this. Any help will be greatly appreciated.

<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>


Solution

  • Like this I guess. Note that you could have done this in SMIL too.

    I've set the animation to be forwards so it remains at the end, otherwise the curve disappears at the end of the animation.

    The console.log line shows you where I got the number from.

    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>