TweenLite Meets Flash Drawing API for Animated Line Drawing Fun

by carl schooff on April 27, 2011 · View Comments

in GreenSock Tweening Platform Tips

This movie requires Flash Player 9

Ok, I was just going to smack a little sample file into a post on the GreenSock forums but figured it would only take a few extra minutes to share it with all of you. Here are 2 fairly basic approaches to creating animated lines with ActionScript 3 Drawing API.

Simple: Smack an onUpdate onto a few simple TweenLite Tweens

The swf at the top of this page just uses 2 TweenLite tweens that call an onUpdate callback function that draws a line to wherever the mc happens to be. Hopefully you have a basic understanding of the ActionScript 3.0 Drawing API.

AS3 Code

import com.greensock.*;
import flash.events.MouseEvent;

var line:Shape = new Shape();
addChild(line);

var startX:Number = mc.x;
var startY:Number = mc.y;

play_btn.addEventListener(MouseEvent.CLICK, startAnimation);

function startAnimation(e:MouseEvent):void
{
	mc.x = startX;
	mc.y = startY;
	TweenMax.to(mc,1,{x:400, y:20, onUpdate:drawLine});
	TweenMax.to(mc,1,{y:250, delay:1, onUpdate:drawLine});
	line.graphics.clear();
	line.graphics.lineStyle(5, 0xFF1C30);
	line.graphics.moveTo(mc.x, mc.y);
}

function drawLine():void
{
	line.graphics.lineTo(mc.x, mc.y);
}

Advanced: Place some clips on stage to mark where you want the lines drawn to and use TimelineMax to sequence the tweens

This movie requires Flash Player 9

This method takes a little more time to set up, but it is sooo easy to edit where the line goes as you can just move around some clips on the stage.

AS3 Code

import com.greensock.*;
import flash.events.MouseEvent;

//create line
var line:Shape = new Shape();
addChild(line);

//position mc at first point
mc.x = p1.x;
mc.y = p1.y;

var tl:TimelineMax = new TimelineMax({paused:true,onUpdate:drawLine});

tl.appendMultiple([
  TweenLite.to(mc, 1, {x:p2.x, y:p2.y}),
  TweenLite.to(mc, 1, {x:p3.x, y:p3.y}),
  TweenLite.to(mc, 1, {x:p4.x, y:p4.y})
  ], 0, TweenAlign.SEQUENCE);

function drawLine():void
{
	line.graphics.lineTo(mc.x, mc.y);
}

play_btn.addEventListener(MouseEvent.CLICK, playTl);

function playTl(e:MouseEvent):void
{
	//kill existing line
	line.graphics.clear();

	//start new line at first point
	line.graphics.lineStyle(5, 0xFFFF00, .5);
	line.graphics.moveTo(p1.x, p1.y);

	tl.restart();

}

**note if you are extra fancy you could use a loop to build your TimelineMax but I didn’t want to get too crazy.

Download Flash CS4 Source Files

SNORKLtv_TweenDraw

BONUS

Thanks to X10′s comment below, I was motivated to try to figure out how to “erase” the line on reverse. I don’t know how well I can explain it, but the ambitious among you should check out the bonus file here:

Use TimelineMax to Draw and ERASE Animated Lines

Post to Twitter Post to Facebook

  • X10

    Brilliant post Carl, could have used something like this earlier in the month, but learning the ‘hard’ way was valuable.
    Shame you can’t use TimelineLite/Max to ‘erase’ the line when reversing through the points.

  • http://www.snorkl.tv/ carl schooff

    Oh!, but you can! I came up with this new method:
    http://bit.ly/erzYe8

    it isn’t battle-tested but it seems to work ok. Check it out.

    thanks for making that point, it had me scratching my head for a bit.

  • X10

    Carl, my hat goes off to you!
    I am going to have a look through to see if I can make it work with Greensock’s BezierThrough plugin and Bezier curves.

  • http://www.facebook.com/profile.php?id=290301287 Devon Franklyn

    Thanks Carl, usefull stuff like always haha. If your bored, try a curved line too :P

  • Oliver

    If I want to draw lines not continuous, what should i do? Thanks a lot! I want to click a button, then draw first line, and second line, and third… These lines are separate. How ever, I can not realize it since spent much times.

  • http://www.snorkl.tv/ carl schooff

    read the article i linked to above on the Drawing API. That offers a much
    better explanation than I can provide. You need to understand lineTo and
    moveTo. and then you can draw any line from anywhere to anywhere.

  • Oliver

    mc.x = 180;
    mc.y = 140;
    TweenMax.to(mc,1,{x:380, y:95, onUpdate:drawLine});

    mc.x = 216;
    mc.y = 52;
    line.graphics.moveTo(216, 52);
    TweenMax.to(mc,1,{x:363, y:217, onUpdate:drawLine})

    I write as above, but always shows the 2nd line, can you tell me what’s wrong. Thanks very much.

  • Ido Dweck

    Hi,

    I’m an almost ignorant to scripting but i could figure out and appreciate this one! it answers almost what i’d like to to… almost because I’m trying to have several lines starting at different points, going through different points and not necessarily starting at the same time… also I tried removing the button without much success… as told – it’s not my area of expertise…
    could you help me figuring it out? 
    btw, how do you control the speed of the drawing?
    many many thanks

  • http://www.snorkl.tv/ carl schooff

    check out greensock’s getting started page. you are going to need to know
    the basics of TweenLite in order to make any process.

    http://www.snorkl.tv/dev/dropdown/dropdown.html

    in short:

    TweenLite.to(mc, 1, {x:100, delay:2});

    this tween will move mc to an x of 100 over the course of 1 second. there
    will be a 2 second delay before the animation starts.

    Thanks for watching.

  • http://twitter.com/procastino tucho mendez

    Hi Carl, and thansk for this post!
    I wonder if you could give me a hint, because I’m completely lost about getting where I need to go.

    I have an array of items, and their positions are set by the user, using input text to set the value of those positions. I got to that point using TweenMax and much of what I learned through your tutorials :) .

    Here is the code:

    import com.greensock.*;import com.greensock.easing.*;

    //set the Arrays
    var temp_txtArray:Array = [Xan_txt, Feb_txt,Mar_txt,Abr_txt];
    var temp_mcArray:Array=[Xan_mc, Feb_mc,Mar_mc,Abr_mc];

    //add event to button
    enterButton.addEventListener(MouseEvent.MOUSE_UP,furrula);

    //function that moves the mc’s to a new place
    function furrula(e:MouseEvent):void
    {
    for (var i:int = 0; i < temp_txtArray.length; i++)
    {
    var temp:Number=530-Number(temp_txtArray[i].text)*10;
    TweenMax.to(temp_mcArray[i],1, {y:temp, ease:Back.easeInOut});
    }
    }

    Now I would like to use your code to draw a line over all the mc's of the temp_mcArray, but I'm unable to do it. I just get the line to be drawn over the mc's initial positions, not over the ending positions after the enterButton is pressed and the tween is done…
    I don't know if I explained myself, if you just had the time to tell me which way to go, I would be really grateful.
    Anyway, thanks a lot for your work!

  • http://www.snorkl.tv/ carl schooff

    when you generate the value of temp inside your loop, it appears that is the value that the mcs are tweening to, so that is the value that you want to draw your line to.

    since you have multiple mcs that are animating, you need to have a separate mc that animates to all the mcs ending points and draws the line.

    what I would do in your loop is push the temp value into a new array, call it endPointsArray or something. when all the mcs are done bouncing around, create a TimelineMax of tweens based on the values in endPointsArray and then implement the drawing technique I used in the tutorial.

    sounds like a cool effect you are going for.

    Carl

  • http://twitter.com/procastino tucho mendez

    Thanks Carl!
    I did what you told me, and I feel I’m a little closer now but… but I can’t get to do it!
    I understand your tutorial, but I can’t make it work when I mix it with my code. I’m quite a newbie and I’m sure it has to be some silly thing, but I don’t get it. 
    Just in case you have the time and kindness to take a look, I uploaded my .fla file, as simplified as possible, here http://www.mediafire.com/?l5fod9czkkl33xp 
    If this ends up being any cool at all, it will all be thanks to you, you are being a great help for me.

  • http://www.snorkl.tv/ carl schooff

    Hey Tucho,

    I think I fixed it: get it here: http://ge.tt/8VI1K55?c

    I have to commend you on the way you took my short directions and
    implemented them in a very good way.

    I made a few comments (i enjoyed reading yours) on some of the changes that
    I made but not everywhere.

    the main problem was that endPoints and tl were declared inside functions so
    they weren’t accessible from other functions. I moved them out of the
    functions and tweaked some minor things.

    Nothing wrong with your code. I like what your app does.

    let me know if you have any questions. I think from what you were to
    accomplish so far you will have no problem seeing what I did.

    Best,

    Carl

  • http://twitter.com/procastino tucho mendez

    Literally, I don’t know how to thank you! :-)
    I got your comments and everything is (now) understandable.
    I’m sure I’ll have questions, but I hope they will be simpler from now on,  I’m trying to develop some materials for my students (I’m a teacher) and your tutorials are really useful for me, I’m learning a lot through them.
    Thanks for your patience!

  • http://twitter.com/procastino tucho mendez

    mmmm… another little question?

    If I input new values and press play again,  the line will be drawn again over the old values, and when it reaches the end it goes back to the beginning and starts again. If i hit a third time, it will do this three times and so on…I figured out that drawing the old values was because of the array that stores endPoints, so I kinda solved it putting a new “reset”button that calls a function {endPoints.splice(0,endPoints.length)}, that way the line is drawn over the new values, but only in the second “pass”.
    I tried to put some killTweensOf, killAll, invalidate inside that button, because I think that the problem is that the timeline stores the old values, but was not able to fix it.

    It is quite an important thing for this project, as long as the kids will have to input different values and watch different results.

    Any idea of how to solve this?I’m sorry to bother so much, I think I got myself in a mess that is way over my skills, I promise I won’t do it again! :-)

  • http://www.snorkl.tv/ carl schooff

    Yes, the timeline remembers everything you previously added. Just do:

    tl= new TimeLineMax()

    Or

    tl.clear()

  • http://twitter.com/procastino tucho mendez

    ouch!
    it was simple… it’s allways simple…
    Hats off, you made my day!

  • http://www.snorkl.tv/ carl schooff

    great. glad it worked for you!

  • Er Ds

    hello there, very thanks for the code. I have a question about this “Draw line “code. What if I want to increase the time scale of t1:TimelineMax by the code

    t1.timeScale = 10; in the function playT1 before restart of t1

    The output I got is not OK. With the increase in timescale, the lines become worst. They start skipping the points. Is anybody knows any solution, plz.. help..   

  • http://www.snorkl.tv/ carl schooff

    yeah that is going to happen. as the timescale increases, the number of opportunities to render points and connect them is going to decrease thus resulting in compromised results.
    you could try forcing the onUpdate function to run each time an individual tween completes:

    TweenLite.to(mc, 1, {x:p2.x, y:p2.y, onUpdate:drawLine})

    not positive it will work, but give it a shot. setting timeScale to 10 is insanely fast, the point of this technique is to be able to see the lines being drawn and in order for that to work you need to give the animation a reasonable amount of time to happen.

  • Caglar

    Carl thanks a lot. It works for reversing but how can I make it go back or forward to a specific time on the timeline? For example, I have a slider and I control the time, whenever I drag the thumb I expect to see only the lines that must be drawn at that time. 

  • http://www.snorkl.tv/ carl schooff

    That’s a cool idea for extending this exercise. From a logic standpoint there is nothing built in to the existing code or TimelineLite to undo the actions that are taken outside of TimelineLite.

    My guess is that it is entirely possible, but you would have to build something to manage/track all the lines as they are being drawn and then create a mechanism to remove certain lines based on the currentProgress of the timeline.

    This is a bit beyond the intention of the exercise or my immediate capacity to provide a solution.

    I will say it could make for an cool code challenge. hmmm.

    thanks for watching. if you or anyone reading this comes up with a solution, please let me know.

    best,

    carl

  • Caglar

    Thanks for quick response. I will post it if I come up with a solution.

    Best,

    Caglar

  • Bill75

    Thanks for sharing this Carl. It really helped me with my World War I planes. I attached country coated lines to each plane and gave it a speed. It makes the point of how much technology changed in the war years. See what you helped make. . . http://flashnhistory.com/FlashPrograms/Plane%20Race.swf

  • http://www.snorkl.tv/ carl schooff

    Very cool. Thanks for sharing! Love seeing what people are using my tutorials for. great job!

blog comments powered by Disqus

Previous post:

Next post: