newbie / how was this done? animated stroke

Copy link to clipboard
Copied
My favorite DPS magazine has this beautiful animated stroke that I am showing below in these iPad screen captures. The stroke starts from upper left corner and progresses up until to lower right. This is DPS and I presume this animation is made in Flash before becoming a DPS html overlay, so I drawed a couples of black lines in Flash with several white rectangle tweens progressively covering the line in order to recreate that effect. That does not work, my SWF ignores the timeline and triggers all tweens at the same time, ruins the effect.
I am not a Flash guy, but do you people know if Flash is the easiest to create this effect?
Many thanks,
Copy link to clipboard
Copied
i didn't gather any info from your screen captures but generally animation that appears as cursive writing is done by using various animated masks. each mask/animation should appear on a distinct layer.

Copy link to clipboard
Copied
Thank you, you mean all this Inside flash, correct? I am not super confident this travels Ok to DPS via Wallaby.

Copy link to clipboard
Copied
By the way my 3 screen captures show an appearing vertical black stroke on the left hand side of the page
Copy link to clipboard
Copied
Although animated masks can offer some advantages, you can do that totally programmatically using Graphics class capabilities.
Below is an example that emulates what you want. It definitely need optimization - just a quick and dirty example.
Just place this code on the first frame of an empty FLA.
stop();
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
var animatedLineOverlay:Shape;
var overlayGraphics:Graphics;
var overlayPoints:Array;
var overlayMargin:Number = 30;
var currentPoints:Object;
var nextPoint:Point;
var sPoint:Point;
var ePoint:Point;
var angle:Number;
var speed:Number = 8;
var advanceX:Number;
var advanceY:Number;
init();
function init():void
{
makeBackground();
definePoints();
makeOverlay();
startAnimation();
}
function startAnimation():void
{
addEventListener(Event.ENTER_FRAME, drawLine);
}
function drawLine(e:Event):void
{
if (!currentPoints)
{
if (overlayPoints.length == 0)
{
removeEventListener(Event.ENTER_FRAME, drawLine);
return;
}
currentPoints = overlayPoints.shift();
if (currentPoints.lineColor)
{
overlayGraphics.lineStyle(1, currentPoints.lineColor, 1, true);
}
sPoint = currentPoints.start;
ePoint = currentPoints.end;
angle = Math.atan2(ePoint.x - sPoint.x, ePoint.y - sPoint.y);
advanceX = speed * Math.sin(angle);
advanceY = speed * Math.cos(angle);
overlayGraphics.moveTo(sPoint.x, sPoint.y);
nextPoint = new Point(sPoint.x, sPoint.y);
}
nextPoint.x += advanceX;
nextPoint.y += advanceY;
overlayGraphics.lineTo(nextPoint.x, nextPoint.y);
if (Point.distance(ePoint, nextPoint) <= speed)
{
overlayGraphics.lineTo(ePoint.x, ePoint.y);
currentPoints = null;
}
}
function definePoints():void
{
var overlayWidth:Number = stage.stageWidth - overlayMargin * 2;
var overlayHeight:Number = stage.stageHeight - overlayMargin * 2;
overlayPoints = [];
overlayPoints.push({start: new Point(0, 0), end: new Point(0, overlayHeight / 6)});
overlayPoints.push({start: new Point(0, overlayHeight * .5), end: new Point(0, overlayHeight)});
overlayPoints.push({start: new Point(0, overlayHeight), end: new Point(overlayWidth / 8, overlayHeight)});
overlayPoints.push({start: new Point(overlayWidth / 8, overlayHeight), end: new Point(overlayWidth / 6, overlayHeight - 50)});
overlayPoints.push({start: new Point(overlayWidth / 6, overlayHeight - 50), end: new Point(overlayWidth * .5, overlayHeight - 50)});
overlayPoints.push({start: new Point(overlayWidth * .5, overlayHeight - 50), end: new Point(overlayWidth - 20, overlayHeight - 50), lineColor: 0xFFFFFF});
overlayPoints.push({start: new Point(overlayWidth - 20, overlayHeight - 50), end: new Point(overlayWidth - 20, overlayHeight - 100)});
overlayPoints.push({start: new Point(overlayWidth - 20, overlayHeight - 100), end: new Point(overlayWidth, overlayHeight - 150)});
overlayPoints.push({start: new Point(overlayWidth, overlayHeight - 150), end: new Point(overlayWidth, overlayHeight - 200)});
}
function makeOverlay():void
{
animatedLineOverlay = new Shape();
overlayGraphics = animatedLineOverlay.graphics;
overlayGraphics.lineStyle(1, 0, 1, true);
overlayGraphics.beginFill(0x000000);
overlayGraphics.drawRect(0, 0, 80, 10);
overlayGraphics.endFill();
animatedLineOverlay.x = animatedLineOverlay.y = overlayMargin;
addChild(animatedLineOverlay);
}
function makeBackground():void
{
graphics.beginFill(0xFF8040);
graphics.drawRect(0, 0, stage.stageWidth * .5, stage.stageHeight);
graphics.endFill();
graphics.beginFill(0x0070DF);
graphics.drawRect(stage.stageWidth * .5, 0, stage.stageWidth * .5, stage.stageHeight);
graphics.endFill();
}

Copy link to clipboard
Copied
I am totally impressed, many thanks for what you call quick and dirty.
The swf movie I get is perfect and ultra light, yet it does not work after I passed the FLA through Wallaby, do you have any clue? My timeline only has one frame, is this the reason?
All best,
Copy link to clipboard
Copied
Sorry, I am not familiar with Wallaby...

Copy link to clipboard
Copied
that's an adobe plugin to convert fla files to html5
Copy link to clipboard
Copied
I know. I have no working knowledge of it for, well, I have very little interest in HTML5...

Copy link to clipboard
Copied
After digging, I now understand Actionscript 3 is not supported by Wallaby nor the JCreate plugin nor the Google converter, so I have to rewrite your code in Javascript to make this compliant with tablet devices. So I will search for an AS3 to JS compiler unless you know other tools about that.
Best,
Copy link to clipboard
Copied
You know that you can create mobile apps in Flash IDE, right?

Copy link to clipboard
Copied
Yes but the backbone of my product remains indesign and Digital Publishing Suite. I can only add external html, so the code such as what you wrote has somehow to fit in this framework.
Copy link to clipboard
Copied
I see.
Rewriting it in JavaScript is not a big deal - syntax is similar in many ways.

Copy link to clipboard
Copied
I am onto it - will check line by line (not knowing either language, amounts to the same).
Thanks again

Copy link to clipboard
Copied
Andrei, I am trying to learn bits of Javascript at the same time as trying to understand this AS3 script. Can you explain in a few lines the sequencing of your script? or point me to similar simpler AS3 codes where I can follow more easily what Flash is doing?
Thanks so much,
Copy link to clipboard
Copied
First, you need to get handle of AS3 drawing API and geometry/math capabilities.
Here is the link to Graphics class documentation:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html
Here is the link to Point API docs:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Point.html
Math is, well, the same as anywhere else.
In JavaScript you will need to get knowledge of its API as well - it is very similar because AS3 and JavaScript are siblings.
Here is a code that I commented as thoroughly as I could:
stop();
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
/**
* Shape which is used to draw line into.
* Basically line drawing itself.
*/
var animatedLineOverlay:Shape;
/**
* Instance of animatedLineOverlay.graphics
* This variable is created to be reused
*/
var overlayGraphics:Graphics;
// array of points between which to draw line
var overlayPoints:Array;
// x and y postions of line drawing
var overlayMargin:Number = 30;
/**
* Used to kepp reference to current start and end points
* between which line is being drawn
*/
var currentPoints:Object;
/**
* Next point to which draw line in the animation.
*
* Declare here so it can be reused.
*/
var nextPoint:Point;
/**
* Line straight segmen starting point.
*/
var sPoint:Point;
/**
* Line straight segment end point
*/
var ePoint:Point;
/**
* Anngle under which to draw line segment
*/
var angle:Number;
/**
* Line draw speed
*/
var speed:Number = 8;
/**
* How far to advance line animation in a single frame along x
*/
var advanceX:Number;
/**
* How far to advance line animation in a single frame along y
*/
var advanceY:Number;
init();
/**
* Inititalizes entire thing by calling specialized functions
*/
function init():void
{
makeBackground();
definePoints();
makeOverlay();
startAnimation();
}
/**
* Starts line animation by adding ENTER_FRAME event listener
*/
function startAnimation():void
{
addEventListener(Event.ENTER_FRAME, drawLine);
}
/**
* ENTER_FRAME event handler
* @param e
*/
function drawLine(e:Event):void
{
// if no currentPoints defined - go through the logic
if (!currentPoints)
{
/**
* since we shorten overlayPoints while animating line
* whyen array is empty - stop animation
*/
if (overlayPoints.length == 0)
{
// stop animation
removeEventListener(Event.ENTER_FRAME, drawLine);
// calling return will effectively exit drawLine function
return;
}
// get point to process by extracting first element in the array
currentPoints = overlayPoints.shift();
// if element contains color property - change line color
if (currentPoints.lineColor)
{
overlayGraphics.lineStyle(1, currentPoints.lineColor, 1, true);
}
// get start and end points
sPoint = currentPoints.start;
ePoint = currentPoints.end;
// calculate angle between the points
angle = Math.atan2(ePoint.x - sPoint.x, ePoint.y - sPoint.y);
// calculate how far line needs to advance along x/y based on the angle
advanceX = speed * Math.sin(angle);
advanceY = speed * Math.cos(angle);
// move line to startgin position
overlayGraphics.moveTo(sPoint.x, sPoint.y);
// starting point position
nextPoint = new Point(sPoint.x, sPoint.y);
}
// advance drawing coordinates
nextPoint.x += advanceX;
nextPoint.y += advanceY;
// add to line segment nextPoint coordinates
overlayGraphics.lineTo(nextPoint.x, nextPoint.y);
/**
* if the lates drawing did not get to the exact target point
* add the difference
*/
if (Point.distance(ePoint, nextPoint) <= speed)
{
// add the difference
overlayGraphics.lineTo(ePoint.x, ePoint.y);
/**
* nullify currentPoints so that on the next frame
* funciont exectures first conditional
*/
currentPoints = null;
}
}
/**
* Creates data for usage in animation.
* Points coordinates are arbitrary.
*/
function definePoints():void
{
// use this variables to make drawing dynamic - based on overall application dimensions
var overlayWidth:Number = stage.stageWidth - overlayMargin * 2;
var overlayHeight:Number = stage.stageHeight - overlayMargin * 2;
overlayPoints = [];
/**
* each array element will be an Object
* each Object will have two properties start and end
* which represent points at which, naturally start and end line segment
*
* points values are totally arbitrary - use your imagination
*/
overlayPoints.push({start: new Point(0, 0), end: new Point(0, overlayHeight / 6)});
overlayPoints.push({start: new Point(0, overlayHeight * .5), end: new Point(0, overlayHeight)});
overlayPoints.push({start: new Point(0, overlayHeight), end: new Point(overlayWidth / 8, overlayHeight)});
overlayPoints.push({start: new Point(overlayWidth / 8, overlayHeight), end: new Point(overlayWidth / 6, overlayHeight - 50)});
overlayPoints.push({start: new Point(overlayWidth / 6, overlayHeight - 50), end: new Point(overlayWidth * .5, overlayHeight - 50)});
// this element also has color property - to change line color at this segment
overlayPoints.push({start: new Point(overlayWidth * .5, overlayHeight - 50), end: new Point(overlayWidth - 20, overlayHeight - 50), lineColor: 0xFFFFFF});
overlayPoints.push({start: new Point(overlayWidth - 20, overlayHeight - 50), end: new Point(overlayWidth - 20, overlayHeight - 100)});
overlayPoints.push({start: new Point(overlayWidth - 20, overlayHeight - 100), end: new Point(overlayWidth, overlayHeight - 150)});
overlayPoints.push({start: new Point(overlayWidth, overlayHeight - 150), end: new Point(overlayWidth, overlayHeight - 200)});
}
/**
* Creates line drawing plain
*/
function makeOverlay():void
{
// instantiate
animatedLineOverlay = new Shape();
// gain reference to the graphics API
overlayGraphics = animatedLineOverlay.graphics;
// define line properties
overlayGraphics.lineStyle(1, 0, 1, true);
overlayGraphics.beginFill(0x000000);
// draw initial rectangle at the top/left
overlayGraphics.drawRect(0, 0, 80, 10);
overlayGraphics.endFill();
// position drawing plain at its margin
animatedLineOverlay.x = animatedLineOverlay.y = overlayMargin;
addChild(animatedLineOverlay);
}
/**
* Makes applpication background.
*/
function makeBackground():void
{
graphics.beginFill(0xFF8040);
graphics.drawRect(0, 0, stage.stageWidth * .5, stage.stageHeight);
graphics.endFill();
graphics.beginFill(0x0070DF);
graphics.drawRect(stage.stageWidth * .5, 0, stage.stageWidth * .5, stage.stageHeight);
graphics.endFill();
}

Copy link to clipboard
Copied
Thanks a million, I will read this in details.
best regards

