TraderZed
TraderZed

Reputation: 215

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

Upvotes: 4

Views: 9457

Answers (3)

john k
john k

Reputation: 6615

SVG has a stroke attribute. Use CSS to change the stroke type to dashed, then change its offset in a javascript loop

Upvotes: -1

Ilya Tikhonov
Ilya Tikhonov

Reputation: 1429

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/

Upvotes: 11

TraderZed
TraderZed

Reputation: 215

Duplicated the path as a solid color so it covers the dashed line. Then, animated the solid color line out, revealing the dashed line below.

http://jsfiddle.net/ehan4/4/

<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"/>
    <path id="top" stroke="#fff" stroke-width="3" fill="none" d="M50.887,170.063v-53.488h55.814"/>
</svg>

<script>
var path = document.querySelector('#top');
var length = path.getTotalLength();
path.style.transition = path.style.WebkitTransition = 'none';
path.style.strokeDasharray = length + ' ' + length;
path.style.strokeDashoffset = '0';

path.getBoundingClientRect();

path.style.transition = path.style.WebkitTransition = 'stroke-dashoffset 2s ease-in-out';
path.style.strokeDashoffset = length;
</script>

Upvotes: 5

Related Questions