Comment tracer un chemin vectoriel progressivement? (Raphaël.js)

comment animer un chemin vectoriel comme s'il était dessiné, progressivement? en d'autres termes, montrez lentement le pixel de chemin par pixel.

j'utilise Raphaël.js , mais si votre réponse n'est pas spécifique à la bibliothèque-comme peut-être il y a un modèle de programmation générale pour faire ce genre de chose (je suis assez nouveau à l'animation vectorielle) - c'est bienvenu!


C'est facile à faire avec les chemins rectilignes, aussi facile qu'un exemple sur cette page ::

path("M114 253").animate({path: "M114 253 L 234 253"});

mais essayer de changer le code sur cette page, dire, de cette façon::

path("M114 26").animate({path: "M114 26 C 24 23 234 253 234 253"});

et vous verrez ce que je veux dire. Le chemin est certainement animé de son état initial (point "M114 26") à l'état final (courbe "C 24 23 234 253 234 253" à partir du point "M114 26"), mais pas d'une manière spécifiée en question, pas comme il est dessiné.

je n'ai pas voir comment animateAlong peut faire. Il peut animer un objet le long d'un chemin, mais comment puis-je faire ce chemin à progressivement spectacle lui-même, tout objet est animée le long?


la solution?

(Via peteorpeter la réponse de .)

semble comme actuellement la meilleure façon de le faire est via 'fake' dashes utilisant raw SVG. Pour l'explication, voir cette démo ou ce document , page 4.

comment produire le dessin progressif?

nous devons utiliser stroke-dasharray et stroke-dashoffset et connaître la longueur de la courbe à dessiner. Ce code ne dessine rien à l'écran pour cercle, ellipse, polyline, polygone ou chemin:

<[element] style="stroke-dasharray:[curve_length],[curve_length]; stroke-dashoffset:[curve_length]"/>

si dans animate element stroke-dashoffset diminution à 0, nous obtenons le dessin progressif de la courbe.

<circle cx="200" cy="200" r="115"
    style="fill:none; stroke:blue; stroke-dasharray:723,723; stroke-dashoffset:723">
    <animate begin="0" attributeName="stroke-dashoffset"
        from="723" to="0" dur="5s" fill="freeze"/>
</circle>

si vous connaissez une meilleure façon, veuillez laisser une réponse.


Mise À Jour (26 Avr. 2012): trouver un exemple qui illustre bien l'idée, voir courbes animées Bézier .

31
demandé sur Community 2011-01-08 01:52:53

11 réponses

j'ai créé un script pour ça: Scribble.js , basé sur ce grand dasharray/dashoffset technique .

il vous suffit d'instancier il overs un tas de SVG <path> s:

var scribble = new Scribble(paths, {duration: 3000});
scribble.erase();
scribble.draw(function () {
    // done
});

--

NB: Full USAGE code ici: https://gist.github.com/abernier/e082a201b0865de1a41f#file-index-html-L31

;)

3
répondu abernier 2016-03-11 16:21:24

peut-être que quelqu'un cherche une réponse, comme moi depuis deux jours maintenant:

// Draw a path and hide it:
var root = paper.path('M0 50L30 50Q100 100 50 50').hide();
var length = root.getTotalLength();

// Setup your animation (in my case jQuery):
element.animate({ 'to': 1 }, {
    duration: 500,
    step: function(pos, fx) {
        var offset = length * fx.pos;
        var subpath = root.getSubpath(0, offset);
        paper.clear();
        paper.path(subpath);
    }
});

qui a fait l'affaire pour moi, seulement en utilisant les méthodes de RaphaelJS.

voici un exemple de jsFiddle comme demandé dans les commentaires, http://jsfiddle.net/eA8bj /

26
répondu davidenke 2012-11-18 04:49:25

Eureka! (Peut - être-en supposant que vous êtes à l'aise de sortir du Royaume amical de Raphaël dans le pur pays SVG...)

vous pouvez utiliser SVG keyTimes et keySplines .

voici un exemple pratique:

http://www.carto.net/svg/samples/animated_bustrack.shtml

...et voici quelques explications potentiellement utiles:

http://msdn.microsoft.com/en-us/library/ms533119 (v=vs 85).aspx

17
répondu peteorpeter 2011-02-22 03:59:30

J'aimerais proposer une solution alternative, Raphaël+JS-only que j'ai utilisée de façon substantielle dans mon propre travail. Elle présente plusieurs avantages par rapport à la solution de davidenke:

  1. n'efface pas le papier à chaque cycle, permettant au chemin animé de coexister avec d'autres éléments;
  2. réutilise un seul chemin avec l'animation progressive de Raphael, ce qui rend les animations plus fluides;
  3. sensiblement moins utilisation intensive des ressources.

Voici la méthode (qui pourrait très facilement être re-refroidie en extension):

function drawpath( canvas, pathstr, duration, attr, callback )
{
    var guide_path = canvas.path( pathstr ).attr( { stroke: "none", fill: "none" } );
    var path = canvas.path( guide_path.getSubpath( 0, 1 ) ).attr( attr );
    var total_length = guide_path.getTotalLength( guide_path );
    var last_point = guide_path.getPointAtLength( 0 );
    var start_time = new Date().getTime();
    var interval_length = 50;
    var result = path;        

    var interval_id = setInterval( function()
    {
        var elapsed_time = new Date().getTime() - start_time;
        var this_length = elapsed_time / duration * total_length;
        var subpathstr = guide_path.getSubpath( 0, this_length );            
        attr.path = subpathstr;

        path.animate( attr, interval_length );
        if ( elapsed_time >= duration )
        {
            clearInterval( interval_id );
            if ( callback != undefined ) callback();
                guide_path.remove();
        }                                       
    }, interval_length );  
    return result;
}

Et voici deux exemples de son utilisation sur mon site: un pour Chemin de la Transformation , et l'autre pour Progressive Lettrage .

10
répondu Kevin Nielsen 2012-10-25 17:18:49

utilisant " pathLength " attribut nous pouvons définir la longueur virtuelle du chemin. A partir de là, nous pouvons utiliser cette longueur virtuelle dans "stroke-dasharray". Ainsi, si nous définissons "pathLength" à 100 unités, nous pouvons définir "stroke-dasharray" à "50,50" qui serait exactement 50%, 50% du chemin!

il y a un problème avec cette approche: le seul navigateur qui supporte cet attribut est Opera 11.

ici est un exemple de animation de dessin de courbe sans javascript ou de longueur codée en dur.(Fonctionne correctement seulement dans Opera 11)

6
répondu Brazhnyk Yuriy 2011-03-21 20:49:29

la solution D'Anton & Peteorpeter se décompose tristement en Chrome lorsque les chemins se compliquent. C'est très bien pour la carte de bus dans cette démo liée. Découvrez cette animation "pétales de fleurs" jsfiddle I créé, qui dessine correctement dans FF10 et Safari5, mais clignote de manière incontrôlable dans Chrome:

http://jsfiddle.net/VjMvz /

(C'est tout HTML et SVG en ligne, pas de javascript.)

je suis toujours à la recherche d'un non-Flash solution pour cela. AnimateAlong ne fera pas l'affaire pour ce que je fais. Raphaël.js pourrait marcher, bien qu'il menace de se transformer en spaghetti de rappel très vite.

Davidenke, pouvez-vous poster un jsfiddle fonctionnel avec votre solution? Je ne peux pas le faire fonctionner. Je reçois une erreur dans Chrome 18 que les noeuds qui sont définis à " display: none "avec votre".cacher" n'ont pas de méthode 'getTotalLength'.

3
répondu Ben 2012-03-24 01:28:10

malheureusement, comme vous semblez être d'accord, vous ne pouvez probablement pas faire cela élégamment dans Raphaël.

Toutefois , si, par quelque coup de %deity% vous n'avez pas besoin de soutien c'est à dire pour cette fonction particulière, vous pourriez renoncer à l'Raphaël API et manipuler l'SVG directement . Puis, peut-être, vous pourriez truquer un masque de rouler le long du chemin et de révéler la ligne à un rythme naturel.

vous pourriez dégrader gracieusement en IE pour simplement montrer le chemin en utilisant Raphaël, sans animation.

2
répondu peteorpeter 2011-02-01 16:25:52

je faisais exactement ça. La première chose que j'ai essayé était la solution D'Anton mais la performance craint.

à la fin, la façon la plus facile d'obtenir le résultat que je voulais était d'utiliser la syntaxe alternative" keyframe " pour la fonction animée.

dessine le chemin final de façon invisible, puis génère un tas de cadres clés en utilisant getSubpath dans une boucle.

crée un nouveau chemin qui est visible et égale la première image clé.

alors faites quelque chose comme:

chemin d'accès.anmimate({ keyFrameObject, le calendrier });

vous ne devriez pas avoir besoin d'une image clé pour chaque pixel que vous voulez dessiner. Après avoir joué avec les paramètres, j'ai trouvé qu'une valeur de 100px par image clé fonctionnait pour la complexité/taille de ce que j'essayais de "dessiner

1
répondu David Meister 2011-05-03 05:00:22

juste une mise à jour de ceci, vous pouvez essayer Lazy Line Painter

1
répondu JackSD 2013-08-02 16:28:37

avez-vous essayé animateAlong de Raphaël ? Vous pouvez le voir en action sur une page Démo .

0
répondu user123444555621 2011-01-08 20:39:41

très bien, voilà ce que je pense... la solution est trop loin d'être idéale.

pour montrer petit à petit le chemin signifie que nous devrions le montrer, comme, point par point. Et les chemins vectoriels ne sont pas constitués de points, mais de courbes, il me semble donc qu'il n'y a pas de façon "naturelle" de "dessiner" graduellement le chemin dans les graphismes vectoriels. (Bien que je sois assez nouveau et que je puisse me tromper.)

Le seul moyen serait de transformer un chemin d'accès à un certain nombre de points et de leur montrer un par un.

actuellement, ma solution consiste à tracer un chemin, le rendre invisible, le fractionner en plusieurs sous-chemins, et montrer que les sous-chemins un par un.

ce N'est pas difficile à faire avec Raphaël, mais ce n'est pas élégant non plus, et assez lent sur un grand chemin. Ne pas accepter ma réponse, en espérant qu'il y ait une meilleure façon...

0
répondu Tony 2011-01-10 01:59:22