| AS3 Bitmap folding with DrawTriangles Example 2. | |
| Tags: As3 Bitmap folding, Drawtriangles, Flash Page Flipping, AS3 uvtData, beginBitmapFill, drawPath. | |
|
Click the printer button and the image is tweened by Flash. Click button again the image is folded and thrown away on a Bezier path. |
|
| In Frame 1: Multi-image loader was replace with a
single loader function. Drag functions were removed and big difference is
the page object is now the container so no offsets are required for ABCD
in frame 3 (the page edges start at 1 pixel since 0 would throw an
infinity error). The bitmapData Array was replaced as a single variable and import Tween was added for the 3D rotation effects. A cubic Bezier curve is used as a motion path after the 3D rotation. |
|
Four empty 'node' clips are the anchor and handle points of the Cubic Bezier. |
|
![]() |
The bitmap fold currently only folds from the top-left corner of the
image. P0 is placed at corner.x and corner.y We have to place p3 extremely to the far right (1000 pixels) for our image to disappear off the stage. p1 and p2: the Bezier's handles to shape the curve. page: is our empty image container and btn1 our invisible hit button. |
| Frame 1 code: | |
stop(); //do not remove stop!
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
var pts=[]; var speed:int = 1; var ii:int=0; var init=true;
var num:int=1; var total:int=10; var loader:Loader; //get our jpg file.
var tearoff=false; var afterDrop=false;
var bmpWidth; var bmpHeight; var frontpage:Sprite = new Sprite; var corner:Sprite = new Sprite;
var matrix:Matrix=new Matrix(); var finished=true;
var bitmapData;
btn1.addEventListener(MouseEvent.CLICK, buttonClicked);
function buttonClicked(e:MouseEvent):void {
btn1.removeEventListener(MouseEvent.CLICK, buttonClicked);
if (finished==true) {
finished=false;
frontpage.graphics.clear();
if (num>total) {num=1;}
getImageFile("paper"+num+".jpg"); num+=1;
} else {
tm4.start();
}
}
function getImageFile(filename) {
loader = new Loader();
loader.load(new URLRequest(filename));
configureListeners(loader.contentLoaderInfo);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
}
function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandler);
}
function loadProgress(event:ProgressEvent):void {
var pcent:Number=event.bytesLoaded/event.bytesTotal*100;
lbar.width=pcent; if(pcent==100){;}
}
function completeHandler(e:Event):void {
bitmapData = e.target.content.bitmapData;
bmpWidth=loader.width; bmpHeight=loader.height;
if (page.getChildByName("frontpage")){
this.removeChild(corner);
page.removeChild(frontpage);
}
frontpage.name="frontpage";
frontpage.x=-bmpWidth/2; frontpage.y=-bmpHeight/2; //offset to center of paper.
matrix.identity();
matrix.translate(page.x,page.y); //use matrix to offset the page registration points.
frontpage.graphics.beginBitmapFill(bitmapData,null,false,true); //draw frontpage.
frontpage.graphics.drawRect(0,0,bmpWidth,bmpHeight);
frontpage.graphics.endFill();
page.addChild(frontpage); //add frontpage to stage.
page.x=300; page.y=-bmpWidth/2; //offset to center of paper.
page.rotation = -90; //rotate it.
this.setChildIndex(printer1, this.numChildren-2); //place printer on top.
tm1.start();
if(init){play(); init=false} //finished - load math functions and frame3.
}
function addDragCorner() {
corner.graphics.beginFill(0xff0000,100);
corner.graphics.drawRect(0,0,20,20);
corner.graphics.endFill();
corner.x=page.x-(bmpWidth/2);
corner.y=page.y-(bmpHeight/2); corner.name="corner"; corner.buttonMode = true;
corner.alpha=0;
this.addChild(corner); //insert the drag box at the top-left corner.
p0.x=corner.x; p0.y=corner.y;
if (num%2) {
p1.x=500;p1.y=400;p2.x=100;p2.y=-400; p3.x=1000;p3.y=-120;
} else {
p1.x=200;p1.y=400;p2.x=1000;p2.y=300; p3.x=900;p3.y=900;
}
CubicBezier(this,{x:p0.x,y:p0.y},{x:p1.x,y:p1.y},{x:p2.x,y:p2.y},{x:p3.x,y:p3.y});
}
///////////////// tweening //////////////////////////////
btn1.addEventListener(MouseEvent.CLICK, buttonClicked);
var tm1:Timer=new Timer(50,1); //delay milliseconds, repeatCount for tween.
var tm2:Timer=new Timer(36,18); //3D flip.
var tm3:Timer=new Timer(36,18); //insert DragCorner.
var tm4:Timer=new Timer(50,1); //follow bezier path.
var myTween:Tween;
for(var i=1;i<=4;i++){
this["tm"+String(i)].addEventListener(TimerEvent.TIMER,this["onTimer"+String(i)]);
this["tm"+String(i)].addEventListener(TimerEvent.TIMER_COMPLETE,this["doneTimer"+String(i)]);
}
function onFinish(e:TweenEvent):void {tm1.reset();tm2.start();}
function onTimer1(e:TimerEvent):void {
myTween = new Tween(page, "y", Regular.easeOut, -bmpWidth/2, 200, 1, true);
myTween.addEventListener(TweenEvent.MOTION_FINISH, onFinish);
}
function onTimer2(e:TimerEvent):void {
this.setChildIndex(printer1, this.numChildren-4);
page.rotationY += 10;page.rotationZ += 5;}
function onTimer3(e:TimerEvent):void {page.rotationY += 10;}
function onTimer4(e:TimerEvent):void {moveobj();}
function doneTimer1(e:TimerEvent):void {}
function doneTimer2(e:TimerEvent):void {tm2.reset();tm3.start();}
function doneTimer3(e:TimerEvent):void {
tm3.reset(); addDragCorner(); lbar.width=1;
btn1.addEventListener(MouseEvent.CLICK, buttonClicked);
}
function doneTimer4(e:TimerEvent):void {}
function CubicBezier(mc,p0, p1, p2, p3) {
pts=[];
//mc.graphics.lineStyle(2,0xffff00); mc.graphics.moveTo(p0.x,p0.y); pts.push({x:p0.x,y:p0.y});
for (var u=0; u <= 1; u += .02) { //50 steps - draw cubic bezier arc.
var x1 = Math.pow(u,3)*(p3.x+3*(p1.x-p2.x)-p0.x)+3*Math.pow(u,2)*(p0.x-2*p1.x+p2.x)+3*u*(p1.x-p0.x)+p0.x;
var y1 = Math.pow(u,3)*(p3.y+3*(p1.y-p2.y)-p0.y)+3*Math.pow(u,2)*(p0.y-2*p1.y+p2.y)+3*u*(p1.y-p0.y)+p0.y;
mc.graphics.lineTo(x1,y1); pts.push({x:x1,y:y1});
}
//mc.graphics.lineTo(p3.x,p3.y);
pts.push({x:p3.x,y:p3.y}); tm4.repeatCount=pts.length;
}
function moveobj() {
if (ii < pts.length-1) {
corner.x=pts[ii].x-p0.x; corner.y=pts[ii].y-p0.y; ii+=speed;
foldpaper();
} else {
tm4.reset(); ii=0; finished=true; buttonClicked(null);
}
ii+=1;
}
| |
| In Frame 2 the functions are the same. | |
| In Frame 3: I replaced the static nodes with new Point() and replaces the mouse.x and mouse.y with the drag corner.x and corner.y which now tears our page off automatically using moveobj(). | |
stop(); //do not remove stop!
var node1:Point = new Point(); var node2:Point = new Point();
var node3:Point = new Point(); var node4:Point = new Point();
var mouse:Point=new Point();
var leftEdge=false; var rightEdge=false; var bottomEdge=false; var topEdge=false;
var A:Point = new Point(1,1); //topleft page
var B:Point = new Point(bmpWidth,1); //topright page
var C:Point = new Point(bmpWidth,bmpHeight); //bottomright page
var D:Point = new Point(1,bmpHeight); //bottomleft page
var N:Point= new Point(); //holds right-angled point of normal.
function foldpaper() { //Main Program Code.
rightEdge=false; bottomEdge=false; leftEdge=false; topEdge=false; tearoff=false;//reset.
mouse.x=corner.x; mouse.y=corner.y;
var midpt:Point = Point.interpolate(A,mouse,.5); //center point of drag line to start corner.
rightAnglePt(A,mouse,midpt,N,1,1) //get right hand normal (pt1,pt2,pt,newpt,lineLength,LR:int=0)
var AB:Point=Intersection(midpt,N,A,B); //Get page's rectangle intersection points.
var BC:Point=Intersection(midpt,N,B,C);
var CD:Point=Intersection(midpt,N,C,D);
var DA:Point=Intersection(midpt,N,D,A);
if(AB.x==0 || AB.y==0 || DA.x==0 || DA.y==0){return;} //can't intersect lines, infinity error.
if(AB.x <= A.x && DA.y <=A.y || CD.x <= D.x && DA.y >=D.y) {tearOffImage(AB,0)} //left-side
if(AB.x >= B.x && BC.y <=B.y || CD.x >= C.x && BC.y >=C.y) {tearOffImage(AB,1)} //right-side
if (tearoff==false) {
if(mouse.y < B.y && BC.y < C.y && mouse.x > A.x) { //right-side top drag special case, things reverse.
node1.x=BC.x; node1.y=BC.y;
node2.x=AB.x; node2.y=AB.y;
PointOnHypotenuse(mouse,DA,node4,-bmpHeight); //missing referance point so extend slope line.
PointToLine(node4,CD,node1,node3); topEdge=true;
} else if(mouse.x < D.x && CD.x < C.x) { //left-side drag special case, things reverse.
node1.x=DA.x; node1.y=DA.y;
node2.x=CD.x; node2.y=CD.y;
PointOnHypotenuse(mouse,AB,node3,-bmpWidth);
PointToLine(node3,BC,node2,node4); leftEdge=true;
} else {
if(AB.x>=A.x && AB.x<=B.x) {node2.x=AB.x; node2.y=AB.y;}
if(BC.y>=B.y && BC.y<=C.y) {node2.x=BC.x; node2.y=BC.y; rightEdge=true;}
if(CD.x>=D.x && CD.x<=C.x) {node1.x=CD.x; node1.y=CD.y; bottomEdge=true;}
if(DA.y>=A.y && DA.y<=D.y) {node1.x=DA.x; node1.y=DA.y;}
PointToLine(mouse,AB,node2,node3); PointToLine(mouse,DA,node1,node4);
}
} //end of if tear off.
DrawTriangles(); //draw the backpage.
}
function DrawTriangles() {
var vertices:Vector.
| |
| Photo fold. FLASH CS4 Profeesssional - ActionScript 3. | |
| Files: photofold.fla //FLASH CS4 photofold.swf //compliled CS4 paper1.jpg, paper2.jpg, paper3.jpg, paper4.jpg, paper5.jpg, paper6.jpg, paper7.jpg, paper8.jpg, paper9.jpg, paper10.jpg photofold.htm //generated flash html page. How to setup:
|
|