Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate the drawing of a dashed svg line

I'm trying to animate an arrow with a dashed line, something like this ------->, but with a horizontal and vertical path, using svg and css animations.

I've tried a couple of different things, animating height and width, using bottom and top, but each way has had something that doesn't quite look good or work well.

I managed to get a path drawn with svg, but the animation will actually remove the dashes and just draw a solid line.

No animation: http://jsfiddle.net/ehan4/2/

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="252px" height="396px" viewBox="0 0 252 396" enable-background="new 0 0 252 396" xml:space="preserve">
<path stroke="#000" stroke-width="1.5" fill="none" d="M50.887,170.063v-53.488h55.814" stroke-dasharray="5,5" stroke-dashoffset="0.00" />

With animation: http://jsfiddle.net/ehan4/1/

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="252px" height="396px" viewBox="0 0 252 396" enable-background="new 0 0 252 396" xml:space="preserve">
<path stroke="#000" stroke-width="1.5" fill="none" d="M50.887,170.063v-53.488h55.814" stroke-dasharray="5,5" stroke-dashoffset="0.00" />

var path = document.querySelector('path');
var length = path.getTotalLength();

path.style.transition = path.style.WebkitTransition = 'none';
path.style.strokeDasharray = length + ' ' + length;
path.style.strokeDashoffset = length;
path.getBoundingClientRect();

path.style.transition = path.style.WebkitTransition = 'stroke-dashoffset 2s ease-in-out';
path.style.strokeDashoffset = '0';

Any thoughts or ideas would be greatly appreciated!

Z

like image 437
TraderZed Avatar asked Dec 07 '22 01:12

TraderZed


1 Answers

This function can animate the drawing of dashed path:

function drawPath(path, options) {
    options = options || {}
    var duration = options.duration || 5000
    var easing = options.easing || 'ease-in-out'
    var reverse = options.reverse || false
    var undraw = options.undraw || false
    var callback = options.callback || function () {}

    var length = path.getTotalLength()
    var dashOffsetStates = [length, 0]
    if (reverse) {
        dashOffsetStates = [length, 2 * length]
    }
    if (undraw) {
        dashOffsetStates.reverse()
    }

    // Clear any previous transition
    path.style.transition = path.style.WebkitTransition = 'none';

    var dashArray = path.style.strokeDasharray || path.getAttribute("stroke-dasharray");

    if (dashArray != '') {
        // dashed path case
        // repeats dash pattern as many times as needed to cover path length
        var dashLength = dashArray.split(/[\s,]/).map(function (a) {
            return parseFloat(a) || 0
        }).reduce(function (a, b) {
            return a + b
        })
        var dashCount = length / dashLength + 1
        var a = new Array(Math.ceil(dashCount)).join(dashArray + " ")
        path.style.strokeDasharray = a + '0' + ' ' + length
    } else {
        // non dashed path case
        path.style.strokeDasharray = length + ' ' + length;
    }
    path.style.strokeDashoffset = dashOffsetStates[0];
    path.getBoundingClientRect();
    path.style.transition = path.style.WebkitTransition =
        'stroke-dashoffset ' + duration + 'ms ' + easing;
    path.style.strokeDashoffset = dashOffsetStates[1]
    setTimeout(function() {
        path.style.strokeDasharray = dashArray //set back original dash array
        callback()
    }, duration)
}

It repeats dash pattern as many times as needed to cover path length and then adds empty dash with length of path. It also animates dash offset, as you do in your example.

Working demo: http://jsfiddle.net/u88bm18b/

like image 115
Ilya Tikhonov Avatar answered Dec 19 '22 09:12

Ilya Tikhonov