📄 drawer.as
字号:
package de.alex_uhlmann.animationpackage.drawing { import de.alex_uhlmann.animationpackage.APCore;import de.alex_uhlmann.animationpackage.animation.AnimationEvent;import de.alex_uhlmann.animationpackage.animation.IAnimatable;import de.alex_uhlmann.animationpackage.animation.ISingleAnimatable;import de.alex_uhlmann.animationpackage.animation.SequenceEvent;import de.alex_uhlmann.animationpackage.utility.IComposite;import de.alex_uhlmann.animationpackage.utility.IVisitor;import de.alex_uhlmann.animationpackage.utility.IVisitorElement;import flash.display.DisplayObject;import flash.display.DisplayObjectContainer;import flash.display.Sprite;public class Drawer extends Shape implements ISingleAnimatable, IOutline, IVisitorElement, IComposite { public static const JOIN:String = "JOIN"; public static const EACH:String = "EACH"; private var childsArr:Array; private var start:Number; private var end:Number; private var firstChild:*; private var currentChild:*; private var childDuration:Number; private var position:Number = 0; private var animateMode:String = "JOIN"; private var percentages:Array; private var backwards:Boolean = false; private var sequenceArr:Array; private var redraw:Boolean = true; private var areMovieclipsInjected:Boolean = false; private var m_lineMovieclip:Sprite; private var m_fillMovieclip:Sprite; public function Drawer(...arguments:Array) { super(); if(arguments[0] is Sprite) { this.mc = arguments[0]; } else { this.mc = this.createClip({name:"apDraw", x:0, y:0}); } this.childsArr = new Array(); this.sequenceArr = new Array(); super.lineStyle(0); this.fillStyle(0); } public function run(...arguments:Array):void { } public function setCurrentPercentage(percentage:Number):void { this.invokeAnimation(percentage, NaN); } public function draw():void { this.redraw = true; this.initLineMovieclip(); this.injectNewMovieclipsToChilds(); this.firstChild = this.childsArr[0]; var i:Number, len:Number = this.childsArr.length; for (i = 0; i < len; i++) { var child:Object = this.childsArr[i]; if(child is Drawer) { child.draw(); } else { this.lineMovieclip.graphics.clear(); if(this.fillMovieclip != null) this.fillMovieclip.graphics.clear(); child.draw(); } } } public function drawBy():void { this.redraw = false; this.initLineMovieclip(); this.injectSingleMovieclipToChilds(); this.lineMovieclip.graphics.lineStyle(this.lineThickness, this.lineRGB, this.lineAlpha, this.linePixelHinting, this.lineScaleMode, this.lineCaps, this.lineJoints, this.lineMiterLimit); var i:Number, len:Number = this.childsArr.length; for (i = 0; i < len; i++) { var child:Object = this.childsArr[i]; if(child is Drawer) { child.drawBy(); } else { if(this.firstChild == null) { this.firstChild = child; this.lineMovieclip.graphics.moveTo(child.getX1(), child.getY1()); } child.reset(); child.drawTo(); } } //this.firstChild = null; this.firstChild = this.childsArr[0]; } public function drawTo():void { //fails silently } public function invokeAnimation(start:Number, end:Number):void { var isGoto:Boolean; var percentage:Number; var child:Object; if(isNaN(end)) { isGoto = true; percentage = end = start; start = 0; } else { isGoto = false; this.start = start; this.end = end; this.setTweening(true); } var i:Number, len:Number = this.childsArr.length; var fChild:Object; var posStart:Number = start / 100 * len; var posEnd:Number = end / 100 * len; this.setStartValue(posStart); this.setEndValue(posEnd); if(this.initialized == false) { this.initLineMovieclip(); if(this.redraw) { this.injectNewMovieclipsToChilds(); } else { this.injectSingleMovieclipToChilds(); this.lineMovieclip.graphics.lineStyle(this.lineThickness, this.lineRGB, this.lineAlpha, this.linePixelHinting, this.lineScaleMode, this.lineCaps, this.lineJoints, this.lineMiterLimit); } this.initialized = true; } else { if(this.redraw) { this.fillMovieclip.graphics.clear(); } else { this.lineMovieclip.graphics.clear(); this.fillMovieclip.graphics.clear(); this.lineMovieclip.graphics.lineStyle(this.lineThickness, this.lineRGB, this.lineAlpha, this.linePixelHinting, this.lineScaleMode, this.lineCaps, this.lineJoints, this.lineMiterLimit); } } if(this.animateMode == Drawer.JOIN) { if(!isGoto) { var details:Object = this.getAnimateDetails(start, end, this.childsArr); this.backwards = details.backwards; this.position = details.position; var roundedPosStart:Number = details.roundedPosStart; var roundedPosEnd:Number = details.roundedPosEnd; this.percentages = details.percentages; fChild = this.currentChild = this.childsArr[roundedPosStart]; this.firstChild = fChild; if(this.redraw) { fChild.movieclip.graphics.clear(); if(isCurve(fChild)) fChild.initControlPoints(); fChild.setInitialized(true); fChild.animate(this.percentages[this.position-1].start, this.percentages[this.position-1].end); } else { this.lineMovieclip.graphics.moveTo(fChild.getX1(), fChild.getY1()); if(isCurve(fChild)) fChild.initControlPoints(); fChild.setInitialized(true); fChild.animateTo(this.percentages[this.position-1].start, this.percentages[this.position-1].end); } } else { if(percentage < 0) { this.invokeAnimation(0, NaN); return; } else if(percentage > 100) { this.invokeAnimation(100, NaN); return; } var posPerc:Number = percentage / 100 * (len); var roundedPosPerc:Number = Math.floor(posPerc); var perc_loc:Number = (posPerc - roundedPosPerc) * 100; this.position = roundedPosPerc + 1; this.currentChild = this.childsArr[roundedPosPerc]; for (i = 0; i < len; i++) { child = this.childsArr[i]; if(i < roundedPosPerc) { child.setCurrentPercentage(100); } else { child.setCurrentPercentage(0); } } this.childsArr[roundedPosPerc].setCurrentPercentage(perc_loc); if(percentage == 0) { this.dispatchEvent(new SequenceEvent(AnimationEvent.START, this.getStartValue(), this.childDuration)); } else if(percentage == 100) { this.dispatchEvent(new SequenceEvent(AnimationEvent.END, this.getEndValue(), this.childDuration)); } else { this.dispatchEvent(new SequenceEvent(AnimationEvent.UPDATE, this.getCurrentValue(), this.childDuration)); } } } else { this.percentages = new Array(); this.position = 1; for (i = 0; i < len; i++) { child = this.childsArr[i]; this.sequenceArr.push(this.childsArr[i+1]); child.addEventListener(AnimationEvent.END, onEnd); this.percentages[i] = {start:start, end:end}; } fChild = this.currentChild = this.childsArr[0]; this.firstChild = fChild; if(start > end) { this.backwards = true; } else { this.backwards = false; } if(this.redraw) { fChild.setInitialized(true); if(isCurve(fChild)) fChild.initControlPoints(); fChild.movieclip.graphics.clear(); fChild.animate(start, end); } else { this.lineMovieclip.graphics.moveTo(fChild.getX1(), fChild.getY1()); fChild.setInitialized(true); if(isCurve(fChild)) fChild.initControlPoints(); fChild.animateTo(start, end); } } if(!isGoto) { this.myAnimator = fChild.myAnimator; this.childDuration = fChild.duration; this.dispatchEvent(new SequenceEvent(AnimationEvent.START, this.getStartValue(), this.childDuration, null, IAnimatable(fChild))); } } private function isCurve(child:*):Boolean { return (child is QuadCurve || child is CubicCurve); } private function initLineMovieclip():void { if(this.m_lineMovieclip == null) { this.m_lineMovieclip = this.createClip({parentMC:this.mc, name:"apDraw"}); } } private function injectNewMovieclipsToChilds():void { if(!this.areMovieclipsInjected) { var i:Number, len:Number = this.childsArr.length; for (i = 0; i < len; i++) { var child:Object = this.childsArr[i]; child.movieclip = this.createClip({parentMC:this.m_lineMovieclip, name:"apDraw"}); } this.areMovieclipsInjected = true; } } private function injectSingleMovieclipToChilds():void { if(!this.areMovieclipsInjected) { var i:Number, len:Number = this.childsArr.length; for (i = 0; i < len; i++) { var child:Object = this.childsArr[i]; child.movieclip = this.m_lineMovieclip; child.reset(); } this.areMovieclipsInjected = true; } } public function animate(start:Number, end:Number):void { this.redraw = true; this.invokeAnimation(start, end); } public function animateBy(start:Number, end:Number):void { this.redraw = false; this.invokeAnimation(start, end); } public function fill():void { this.m_fillMovieclip = this.createClip({parentMC:this.mc, name:"apDraw"}); /* * TRICKY: Drawer creates two movieclips. One for the outline and one for the fill. * This workaround is needed because MovieClip.beginFill * and MovieClip.endFill only work in one frame. If the user uses animate and wants to fill * the shape afterwards this workaround comes into play. Furthermore, the user can manipulate the * fill and outline by itself. */ this.m_fillMovieclip.graphics.lineStyle(0,0,0); var penPos:Object = this.firstChild.getPenPosition(); penPos.x = this.firstChild.getX1(); penPos.y = this.firstChild.getY1(); /* * TRICKY: prevent the MovieClip.moveTo() to be invoked on every child. * Tell each child that the pen position is already in place. * In MovieClip.beginFill() - endFill() blocks the moveTo() method * shall only be invoked once before beginFill(). */ this.m_fillMovieclip.graphics.moveTo(penPos.x, penPos.y); this.firstChild.setPenPosition(penPos); if (!isNaN(this.fillRGB) && this.fillGradient == false) { this.m_fillMovieclip.graphics.beginFill(this.fillRGB, this.fillAlpha); } else if (this.fillGradient == true){ this.m_fillMovieclip.graphics.beginGradientFill(this.gradientFillType, this.gradientColors, this.gradientAlphas, this.gradientRatios, this.gradientMatrix, this.gradientSpreadMethod, this.gradientInterpolationMethod, this.gradientFocalPointRatio); } //Hijack children to draw the outline of the fill movieclip. this.drawFillOutline(); //The fill should stay behind the outline. this.swapChilds(this.mc, this.m_lineMovieclip, this.m_fillMovieclip); this.m_fillMovieclip.graphics.endFill(); } private function swapChilds(parentChild:DisplayObjectContainer, bottomChild:DisplayObjectContainer, topChild:DisplayObject):void { var removed:DisplayObject = parentChild.removeChild(topChild); parentChild.addChildAt(removed, bottomChild.getChildIndex + 1); } private function drawFillOutline():void { var lastChild:Object = this.firstChild; var i:Number, len:Number = this.childsArr.length; for (i = 0; i < len; i++) { var child:Object = this.childsArr[i]; if(child is DashLine) { child.reset(); child = new Line(child.getX1(),child.getY1(), child.getX2(),child.getY2()); } //the fill doesn't need an outline. But save properties before overwriting. var lineThickness:Number = child.lineThickness; var lineRGB:Number = child.lineRGB; var lineAlpha:Number = child.lineAlpha; var linePixelHinting:Number = child.linePixelHinting; var lineScaleMode:Number = child.lineScaleMode; var lineCaps:Number = child.lineCaps; var lineJoints:Number = child.lineJoints; var lineMiterLimit:Number = child.lineMiterLimit; child.lineStyle(0,0,0); child.setPenPosition(lastChild.getPenPosition()); var origMC:Sprite = child.movieclip; child.movieclip = this.m_fillMovieclip; if(child is Drawer) { child.draw();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -