0

I need to draw basic geometric shapes progressively. That is, when I draw a line, you need to see it extend as in an animation. There are several questions here on how to do it, and I adopted this approach.

My problems start when some lines have been drawn already, and after the user clicks a button, several more lines should be drawn. The drawing of the new lines happens in a very uneven way.

I have made a jsfiddle to illustrate. It starts with two lines being drawn properly. Then, if the user clicks 'Draw next', two more lines are drawn, but the drawing is not smooth.

I have been trying to debug, and there is some trouble with the step function of jquery's animate.

var stepCount = 0;
$('path[fill*="none"]').animate({
    'to': 1
}, {
    duration: duration,
        step: function(pos, fx) {
    //console.log("fx = ", fx);
    stepCount += 1;
        var offset = length * fx.pos;
        var subpath = line.getSubpath(0, offset);
        canvas.path(subpath).attr({

           'stroke-width': 2,
           stroke: "black"
        });
        },
    complete: function() {
    console.log("stepCount = ", stepCount);
    }
});

I have counted the steps, and logged them for each line in the complete function:

stepCount =  139
stepCount =  140
stepCount =  278
stepCount =  1261
stepCount =  1262
 ....
stepCount =  2318

so the first two stepCounts, represent the first two lines. 139, 140, which is reasonable. Then the third line gets a count of 278 - double the amount of steps. But for the fourth, it goes haywire, it prints out a long list of stepCounts from 1261 to 2318.

I could use some help with this :-)

correction: the third stepCount log happens after the first two lines have been drawn, and before the user clicks 'Draw next'.

solved: ok, still using the approach of progressively drawing ever longer subpaths, I modified the jsfiddle by using melc's solution. I also solved this unholy path mess in the DOM which David Fregoli pointed out. On every iteration of the step function, I remove the previous subpath. And finally, in the complete function I show the original path. This not only makes for a clean DOM, but also solves some anti-aliasing problems.

Community
  • 1
  • 1
devboell
  • 1,180
  • 2
  • 16
  • 34
  • you are creating a new element for every step, at the end the DOM is riddled with a ton of them (one for each step, overlaid one on the other). you should just alter a single element's attributes – David Fregoli Nov 08 '13 at 11:15
  • I am using Raphael, but this progressive line drawing is not supported. I got this approach from other SO questions, which seem to be approved by many others. – devboell Nov 08 '13 at 11:22
  • I am not sure where I am creating elements for every step that you mention. But I am curious why it works well for the first two lines, and then for the other two lines things get messed up. – devboell Nov 08 '13 at 11:25
  • 1
    it doesn't work well at all. after drawing the first two lines you have **310** `path` elements on the canvas. – David Fregoli Nov 08 '13 at 11:26

2 Answers2

2

in the renderPath function you are querying the DOM for ALL the <path> elements in the page and animating every single one.

David Fregoli
  • 3,377
  • 1
  • 19
  • 40
  • mmh, thanks for your comments ... I'll study this some more, cheers. – devboell Nov 08 '13 at 11:28
  • every time you call `canvas.path` it creates a new `path`. you should instead store the one that's created and animate its width attribute – David Fregoli Nov 08 '13 at 11:29
  • I see what you mean, and I'll study it some more. But I am still in the dark as to why the complete function gets called so often after the 'draw next' is clicked – devboell Nov 08 '13 at 11:38
2

The selector $('path[fill*="none"]').animate({ selects all path elements. To make it work you need to replace it with $(line.node).animate({ .

melc
  • 11,523
  • 3
  • 36
  • 41