这个主要是把一张绘制有几个图像,并且有连续关系的位图利用BitmapData类的copyPixels实例方法截取位图上面的部分图像,然后利用ENTER_FRAME事件或者Timer事件制作动画!
在这个方法里面有好几个重要参数
copyPixels(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, alphaBitmapData:BitmapData = null, alphaPoint:Point = null, mergeAlpha:Boolean = false) sourceBitmapData:要制作动画的图片源 sourceRect:这个参数是一个Rectangle,它表示在源位图上开始切割的坐标,宽,高 destPoint:这个表示把切割好的位图作为Bitmap类的源的时候,左上角所在的坐标(我知道这样解析很难明白,但是我想不到其他的解析方式了) 其他参数请看帮助,因为我也没有去具体了解过,也很少用到!
要想你的位图动起来,还需要在制作位图的时候注意每一个图像之间要有一定的间隔,而且最好都在一个固定大小的矩形内。
好了现在把整个类的代码贴出来~!
因为我想用在项目中,所以也写了它的一个父类和一个支持多帧的类
所以工有三个类(DisplaySuper,BmpMovieClip,MultiFrameBmpMovieClip)
DisplaySuper类的代码(很简单):
制作动画的主要类BmpMovieClip:package kongfu { import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.Sprite; /** * ... * @author kongfuzhou */ public class DisplaySuper extends Sprite { public var parentDpl:DisplayObjectContainer; public function DisplaySuper(self:DisplaySuper) { if (self!=this) { throw new Error("abstract class can't new a instance!"); } } /** * 设置显示对象的坐标 * @param xp * @param yp * @param basePro 居于某个宽高居中显示 {w:500,h:500} * @example */ public function setPosOrCenter(xp:Number=0,yp:Number=0,basePro:Object=null):void { if (basePro && basePro.w && basePro.h) { this.x = (basePro.w - this.width) / 2; this.y = (basePro.h - this.height) / 2; }else { this.x = xp; this.y = yp; } } protected function removeMySelf():void { if (this.parent) { this.parent.removeChild(this); } } } }
package kongfu { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.events.Event; import flash.events.TimerEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.utils.Timer; /** * 实现将连续位图转换成动画的类 * @author kongfuzhou */ public class BmpMovieClip extends DisplaySuper { /** * 各种属性 * * @example var obj:Object = { * startXY:{startX:Number,startY:Number}, sizeDiff: { xDiff:106, yDiff:119 }, xDiff:左右两张图的x坐标间隔,yDiff:上下两张图的y坐标间隔 sizePos: { w:80, h:60}, control: { len:12, col:8, row:2 } }; */ private var vars:Object; /** * 最终显示的位图 */ private var bmp_mc:Bitmap; /** * 源位图数据 */ public var bmpdResouce:BitmapData; /** * 最终位图数据 */ private var bmpMcData:BitmapData; private var index:int = 0; private var startPoint:Point; private var rectDataArr:Array; private var frameRate:int; public var firstIsEnd:Boolean = false; private var frameTimer:Timer; private var transParent:Boolean = true; private var color:uint = 0x00ffffff; private var resBmpdObj:Object; private var boolObj:Object; public var isStop:Boolean = true; public var oneTimesFunc:Function; /** * 构造函数 * * @param vars 调用动画的各种属性 * @param resBmpdObj {bmpdRes:BitmapData,bmpdCs:Class} * @param parentDpl 父层 * @param boolObj 该对像的属性是boolean类型的{opentFrameEvent:Boolean=true,useTimer:Boolean=false,autoPlay:Boolean=false} * @param frameRate 使用timer来进行切割位图做动画时的虚拟帧频 * @param startPoint destPoint参数 * @param rectDataArr BitmapData实例的copyPixels函数里面的Rectangle参数的参数(当你想每一个图片的宽、高、切割的X和Y坐标是自己随意定义的时传该参数) */ public function BmpMovieClip(vars:Object, resBmpdObj:Object, parentDpl:DisplayObjectContainer, boolObj:Object = null, frameRate:int = 0, startPoint:Point = null, rectDataArr:Array = null) { super(this); this.boolObj = boolObj; this.boolObj == null ? this.boolObj = {opentFrameEvent: true, useTimer: false, autoPlay: true} : ""; this.boolObj.opentFrameEvent == null ? this.boolObj.opentFrameEvent = true : ""; this.boolObj.useTimer == null ? this.boolObj.useTimer = false : ""; this.boolObj.autoPlay == null ? this.boolObj.autoPlay = true : ""; this.resBmpdObj = resBmpdObj; this.frameRate = frameRate; this.rectDataArr = rectDataArr; this.startPoint = startPoint; this.startPoint == null ? this.startPoint = new Point(0, 0) : ""; this.parentDpl = parentDpl; this.vars = vars; init(); } private function init():void { if (this.vars.control == null || this.vars.startXY == null || this.vars.sizeDiff == null || this.vars.sizePos == null) { throw new Error("vars's property must four or more!"); } this.rectDataArr ? this.vars.control.len = this.rectDataArr.length : ""; this.bmp_mc = new Bitmap(); this.vars.transParent ? this.transParent = this.vars.transParent : ""; this.vars.color ? this.color = this.vars.color : ""; this.bmpMcData = new BitmapData(this.vars.sizePos.w, this.vars.sizePos.h, this.transParent, this.color); if (this.resBmpdObj.bmpdRes) { this.bmpdResouce = this.resBmpdObj.bmpdRes; } else if (this.resBmpdObj.bmpdCs) { this.bmpdResouce = new this.resBmpdObj.bmpdCs(); } if (this.resBmpdObj.bmpdRes == null && this.resBmpdObj.bmpdCs == null) { throw new Error("resBmpdObj must be not null!"); } if (this.bmpdResouce) { this.bmp_mc.bitmapData = this.bmpMcData; this.addChild(this.bmp_mc); this.parentDpl ? this.parentDpl.addChild(this) : ""; if (this.boolObj.useTimer == true) { addTimerEvent(); } } if (this.boolObj.autoPlay == true) { play(); } else { letItMove(); } } private function addTimerEvent():void { this.boolObj.opentFrameEvent = false; this.frameRate == 0 ? this.frameRate = 30 : ""; this.frameTimer = new Timer(int(1000 / this.frameRate)); this.frameTimer.addEventListener(TimerEvent.TIMER, timerHandler); } /** * 播放 */ public function play():void { if (this.boolObj.useTimer == true) { if (this.frameTimer.hasEventListener(TimerEvent.TIMER)) { this.frameTimer.start(); } else { addTimerEvent(); this.frameTimer.start(); } } else if (this.boolObj.opentFrameEvent == true) { this.addEventListener(Event.ENTER_FRAME, onEnterFrame); } } /** * 停止在第一个画面 */ public function stop():void { this.removeEvent(); this.index = 0; letItMove(); } private function timerHandler(e:TimerEvent):void { letItMove(); } private function onEnterFrame(e:Event):void { letItMove(); } /** * 截取bitmapdata上面的图像生成动画 */ public function letItMove():void { if (this.index < this.vars.control.len) { if (this.rectDataArr) { var obj:Object = this.rectDataArr[this.index]; if (obj==null || obj.xp==null || obj.yp==null || obj.w==null || obj.h==null) { throw new Error(" bitmapData.copyPixels() args of Rectangle got a unable args!"); } this.bmpMcData.copyPixels(this.bmpdResouce, new Rectangle(obj.xp, obj.yp, obj.w, obj.h), new Point((this.width - obj.w) / 2, 0)) } else { var xp:Number = this.vars.startXY.startX + (this.index % this.vars.control.col) * this.vars.sizeDiff.xDiff; var yp:Number = this.vars.startXY.startY + int(this.index / this.vars.control.col) * this.vars.sizeDiff.yDiff; this.bmpMcData.copyPixels(this.bmpdResouce, new Rectangle(xp, yp, this.vars.sizePos.w, this.vars.sizePos.h), this.startPoint); } this.index++; } else if (this.oneTimesFunc != null) { this.firstIsEnd = true; this.oneTimesFunc(); } else { this.index = 0; } } /** * 把自己从显示列表中删除并且删除事件侦听器 */ public function remove():void { this.removeMySelf(); removeEvent(); } /** * 删除事件侦听器 */ public function removeEvent():void { if (this.boolObj.opentFrameEvent == true) { this.removeEventListener(Event.ENTER_FRAME, onEnterFrame); } if (this.boolObj.useTimer == true) { this.frameTimer.removeEventListener(TimerEvent.TIMER, timerHandler); } } } }
制作多帧动画的类MultiFrameBmpMovieClip:
package kongfu { import flash.display.DisplayObjectContainer; import flash.events.Event; import flash.utils.Dictionary; /** * 多帧位图mc * ... * @author kongfuzhou */ public class MultiFrameBmpMovieClip extends DisplaySuper { private var framesObj:Object = new Object(); private var framesArr:Array; public var curFrameBmp_mc:BmpMovieClip; public var totalFrames:int; public var curFrameLabel:String; public var curFrame:int; private var framesDict:Dictionary = new Dictionary(); private var frameLabelsDict:Dictionary = new Dictionary(); private var curIndex:int = 1; /** * @param framesObj 每一帧的 * @param parentDlp 父层 */ public function MultiFrameBmpMovieClip(framesArr:Array, parentDlp:DisplayObjectContainer = null) { super(this); this.parentDpl = parentDlp; this.framesArr = framesArr; init(); } private function init():void { if (this.framesArr) { var index:int = 0; for (var i in this.framesArr) { index++; if (i is Number) { var str:String = "frame" + (i + 1); this.framesObj[str] = this.framesArr[i]; this.frameLabelsDict[this.framesObj[str]] = str; } else if (i is String) { this.framesObj[i] = this.framesArr[i]; this.frameLabelsDict[this.framesObj[i]] = i; } this.framesDict[this.framesArr[i]] = index; if (index == 1) { setCurFrame(this.framesArr[i]); } } setTotalFrame(); gotoPlay(); } else { this.framesArr = new Array(); } if (this.parentDpl) { this.parentDpl.addChild(this); } } /** * 播放某帧 * @param frame 帧名字符串,数字也可以直接输入 */ public function gotoStop(frame:String):void { var fm:Number = Number(frame); if (isNaN(fm)) { //不是数字 if (this.framesObj[frame]) { setShow(this.framesObj[frame]); } } else { //是数字 if (this.framesArr[fm - 1]) { setShow(this.framesArr[fm - 1]); } } } /** * 播放所有帧 */ public function gotoPlay():void { //trace("gotoPlay: curIndex = "+this.curIndex+" totalFrames = "+this.totalFrames); if (this.curIndex < this.totalFrames) { (this.framesArr[this.curIndex - 1] as BmpMovieClip).oneTimesFunc = playAll; (this.framesArr[this.curIndex - 1] as BmpMovieClip).play(); } } /** * 控制播放所有帧 */ private function playAll():void { if (this.curIndex > this.totalFrames) { for each (var item:BmpMovieClip in this.framesObj) { item.removeEvent(); } return; } if (this.framesArr[this.curIndex - 1]) { if ((this.framesArr[this.curIndex - 1] as BmpMovieClip).firstIsEnd) { this.curIndex++; } else { if (this.numChildren > 1) { while (this.numChildren > 0) { this.removeChildAt(0); } this.addChild(this.framesArr[this.curIndex - 1]); setCurFrame(this.framesArr[this.curIndex - 1]); } else if (this.numChildren == 1) { var child:BmpMovieClip = (this.getChildAt(0) as BmpMovieClip); if (child != this.framesArr[this.curIndex - 1]) { this.removeChildAt(0); this.addChild(this.framesArr[this.curIndex - 1]); setCurFrame(this.framesArr[this.curIndex - 1]); } else { (this.framesArr[this.curIndex - 1] as BmpMovieClip).oneTimesFunc = playAll; (this.framesArr[this.curIndex - 1] as BmpMovieClip).play(); } } else { this.addChild(this.framesArr[this.curIndex - 1]); setCurFrame(this.framesArr[this.curIndex - 1]); } } } } private function setCurFrame(bmp_mc:BmpMovieClip):void { if (this.framesDict[bmp_mc]) { this.curFrame = this.framesDict[bmp_mc]; } if (this.frameLabelsDict[bmp_mc]) { this.curFrameLabel = this.frameLabelsDict[bmp_mc]; } this.curFrameBmp_mc = bmp_mc; this.curFrameBmp_mc.play(); this.addChild(this.curFrameBmp_mc); } /** * 增加帧 * @param frame 帧标签 * @param addBmpMc 该帧的动画 */ public function addFrame(frame:String, addBmpMc:BmpMovieClip):void { var fm:Number = Number(frame); if (isNaN(fm)) { //不是数字 if (this.framesObj[frame]) { throw new Error("this framlabel is exit!"); } else { this.framesObj[frame] = addBmpMc; this.frameLabelsDict[addBmpMc] = frame; } } else { //是数字 if (this.framesArr[fm - 1] || (fm - 1) < 0) { throw new Error("this framlabel is not exit!"); } else { var str:String = "frame" + (this.framesArr.length + 1); this.framesObj[str] = addBmpMc; this.frameLabelsDict[addBmpMc] = str; } } this.framesArr.push(addBmpMc); this.framesDict[addBmpMc] = this.framesArr.length; this.setTotalFrame(); } /** * 删除帧 * @param frame */ public function removeFrame(frame:String):void { var fm:Number = Number(frame); if (isNaN(fm)) { //不是数字 for (var i in this.framesArr) { if (this.framesArr[i] == this.framesObj[frame]) { this.framesArr.splice(i, 1); break; } } (this.framesObj[frame] as BmpMovieClip).remove(); this.framesObj[frame] = null; } else { //是数字 var j:int = int(frame); if (this.framesArr[j - 1]) { for (var frameName in this.framesObj) { if (this.framesObj[frameName] == this.framesArr[j - 1]) { this.framesObj[frameName] = null; break; } } (this.framesArr[j - 1] as BmpMovieClip).remove(); this.framesArr.splice(j - 1, 1); } } this.setTotalFrame(); setFrameDict(); } /** * 显示某帧内容 * @param showBmp_mc 该帧上的动画 */ private function setShow(showBmp_mc:BmpMovieClip):void { while (this.numChildren > 0) { this.removeChildAt(0); } setCurFrame(showBmp_mc); } /** * 设置总帧数 */ private function setTotalFrame():void { this.totalFrames = this.framesArr.length; } /** * 设置每个对象对应的帧 */ private function setFrameDict():void { var index:int = 0; for (var i in this.framesObj) { index++; this.framesDict[this.framesObj[i]] = index; this.frameLabelsDict[this.framesObj[i]] = i; } } public function remove():void { this.removeMySelf(); } } }
可以到我的微盘下载完整的测试程序和图片素材!
地址: http://vdisk.weibo.com/s/jH3tR