直接上源码,不多说了:
只要有下面这边个类,复制到项目中;运行:TestDialogueUtil.as即可;
package { import flash.events.TimerEvent; import flash.text.TextField; import flash.text.TextFormat; import flash.utils.Timer; import flash.utils.getTimer; /** * 游戏(剧情)对白(动画)工具 * @author jave.lin * @date 2013-7-24 */ public class DialogueUtil{ private static var timer:Timer; // private static const tfPool:Vector. = new Vector. (); // // private static const dataPool:Vector. = new Vector. (); // // private static const dataArr:Vector. = new Vector. (); private static const tfPool:Array = []; private static const dataPool:Array = []; private static const dataArr:Array = []; private static const delay:Number = 60 / 1000; private static const minDelay:Number = 16.6; private static function getData():PopData{ return dataPool.length > 0 ? dataPool.shift() : new PopData(); } private static function pushData(data:PopData):void{ data.tf = null; data.htmlTxt = null; data.duration = NaN; data.complete = null; pushTf(data.helperTf); data.helperTf = null; data.curIdx = NaN; data.update = NaN; data.interval = NaN; data.increaseNum = NaN; data.lastTime = -1; dataPool.push(data); } private static function getTf():TextField{ return tfPool.length > 0 ? tfPool.shift() : new TextField(); } private static function pushTf(tf:TextField):void{ if(!tf) return; tfPool.push(tf); } private static function getDataByTf(tf:TextField):PopData{ if(!tf) return null; for each (var data:PopData in dataArr){ if(data.tf == tf) return data; } return null; } public static function show(htmlTxt:String, tf:TextField, duration:Number, complete:Function = null):void{ //先endShow endShow(tf); //再执行 tf.text = ""; var data:PopData = getData(); data.htmlTxt = htmlTxt; data.tf = tf; data.duration = duration; data.complete = complete; data.helperTf = getTf(); data.helperTf.defaultTextFormat = data.tf.defaultTextFormat; data.helperTf.setTextFormat(data.tf.defaultTextFormat); data.helperTf.multiline = data.tf.multiline; data.helperTf.wordWrap = data.tf.wordWrap; data.helperTf.htmlText = htmlTxt; data.curIdx = 0; data.update = 0; data.interval = duration / data.helperTf.text.length; if(minDelay > data.interval){ data.increaseNum = minDelay / data.interval + (minDelay % data.interval != 0 ? 1 : 0); }else{ data.increaseNum = 0; } dataArr.push(data); start(); } public static function endShow(tf:TextField):void{ var data:PopData = getDataByTf(tf); if(!data) return; data.tf.htmlText = data.htmlTxt; if(data.complete != null) data.complete(); removeData(data); } private static function removeData(data:PopData):void{ var idx:int = dataArr.indexOf(data); if(idx != -1){ dataArr.splice(idx, 1); } pushData(data); } private static function start():void{ if(dataArr.length == 0) return; if(!timer){ timer = new Timer(delay); timer.addEventListener(TimerEvent.TIMER, onTimer); } timer.start(); } private static function onTimer(e:TimerEvent):void{ for each (var data:PopData in dataArr){ popTxt(data); } } private static function popTxt(data:PopData):void{ if(data.lastTime == -1){ data.lastTime = getTimer(); } if(data.curIdx != 0){ var time:int = getTimer(); data.update += time - data.lastTime; if(data.update >= data.interval){ data.update -= data.interval; data.lastTime = time; }else{ return; } } var i:int = 0; if(data.increaseNum != 0){ while(i++ < data.increaseNum && data.curIdx < data.helperTf.length){ pop(data); } }else{ pop(data); } if(data.curIdx >= data.helperTf.text.length){ endShow(data.tf); if(dataArr.length == 0){ timer.stop(); } } } private static function pop(data:PopData):void{ var endIdx:int = Math.min(data.curIdx + 1, data.helperTf.length); var format:TextFormat = data.helperTf.getTextFormat(data.curIdx,endIdx); var newChar:String = data.helperTf.text.charAt(data.curIdx); if(newChar == '\r'){ newChar = '\n'; } data.tf.appendText(newChar); data.tf.setTextFormat(format,data.curIdx, endIdx); data.curIdx++; } } } import flash.text.TextField; class PopData{ public var tf:TextField; public var htmlTxt:String; public var duration:Number; public var complete:Function; public var helperTf:TextField; public var curIdx:int; public var update:Number; public var interval:Number; public var increaseNum:int; public var lastTime:int = -1; }
package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.MouseEvent; import flash.events.TextEvent; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; /** * description * @author jave.lin * @date 2013-7-24 */ [SWF(width="1000",height="600")] public class TestDialogueUtil extends Sprite{ private var tf:TextField; private var tf1:TextField; private var tf2:TextField; public function TestDialogueUtil(){ super(); stage.frameRate = 60; stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.color = 0x888888; tf = getTf(); tf.x = 100; tf.y = 100; addChild(tf); tf1 = getTf(); tf1.x = 250; tf1.y = 100; addChild(tf1); tf2 = getTf(); tf2.x = 400; tf2.y = 100; addChild(tf2); var msg:String = "<font color='#ff0000'>你好</font>lsdjfalk<u>dfja</u>fdasdfafafd<font color='#00ff00'><a href='event:test'><u>adfadf</u></a></font>adfadfafaladjflakdjflasdjflakjdflaksjdflaskdjflaskdjflakdsjflaskdjf"; DialogueUtil.show(msg, tf, 10000, complete); tf1.htmlText = msg; DialogueUtil.show(msg, tf2, 5000, complete); function complete():void{ trace("complete"); } function getTf():TextField{ var tf:TextField = new TextField(); tf.autoSize = TextFieldAutoSize.LEFT; var format:TextFormat = tf.defaultTextFormat; format.size = 12; format.color = 0xffffff; format.font = "Simsun"; tf.defaultTextFormat = format; tf.setTextFormat(format); // tf.width = 100; // tf.height = 500; tf.multiline = true; tf.wordWrap = true; tf.border = true; tf.borderColor = 0; tf.background = true; tf.backgroundColor = 0x888888; return tf; } stage.addEventListener(MouseEvent.CLICK, onClick); tf.addEventListener(TextEvent.LINK, onLink); tf1.addEventListener(TextEvent.LINK, onLink); } private function onLink(e:TextEvent):void{ trace(e.text); } private function onClick(e:MouseEvent):void{ DialogueUtil.endShow(tf); } } }