显示对象处理

发布时间:2015-10-29

  几乎所有的显示对象上的处理与AS3相同,本教程的所有代码示例都是使用LayaFlash进行编译,阅读本篇教程前需要先阅读LayaFlash新手入门教程。


1.资源加载器Loader

   LayaFlash实现的Loader类可以加载jpg、png、gif格式图片、LayaFlash资源转换工具转换后的swf文件以及其他二进制格式文件,并能使用应用域(ApplicationDomain)反射的方式获取资源。与AS3中Loader类的区别在于以下两点:

1.1.加载图片资源时不支持ProgressEvent.PROGRESS事件

  使用LayaFlash开发项目时要避免使用ProgressEven事件监测图片资源的加载进度,LayaFlash 转换现有的AS3项目时,要使用其他方案替换这个事件实现的图片进度监测功能,例如在加载过程的时候显示循环动画表示游戏正处于加载图片素材的状态。

1.2.loadBytes方法不能用于加载图片的二进制数据

  LayaFlash会把AS3代码加载到的图片资源转换为H5中的Image对象,H5不能从Image对象中得到二进制的数据,因此在使用LayaFlash开发或转换项目时要注意不能使用Loader对象的loadBytes方法加载图片二进制数据。

  Loader示例源码下载:layaFlashLoader.rar

  使用Loader的代码示例:

package
{
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;
    import flash.text.TextField;
    import flash.text.TextFormat;
    
    [SWF(width=800,height=600,backgroundColor=0xffffff,frameRate=60)]
    public class Main extends Sprite
    {
        public function Main()
        {

            IFlash.setSize(800, 600);//2D项目中设置场景尺寸
            IFlash.setOrientationEx(1); //是否为横屏模式
            IFlash.setBgcolor("#ffffff"); //背景色
            IFlash.showInfo(false); //是否显示帧率
            if(stage)
                init();
            else
                addEventListener(Event.ADDED_TO_STAGE, init);
        }
         private function init(event:Event = null):void 
         {
            
            this.stage.scaleMode = StageScaleMode.NO_SCALE;
            this.stage.align = StageAlign.TOP_LEFT;
            
           
            
            loadImage();
          }
        
        /**
         * 加载外部图片资源
         * 
         */
          private function loadImage():void 
          {
              var loader:Loader = new Loader();
              loader.contentLoaderInfo.addEventListener(Event.COMPLETE, 
              loadImageComplete);
              loader.load(new URLRequest("assets/chengxuyuan.png"));
            }
           private function loadImageComplete(event:Event):void 
           {
               var loaderInfo:LoaderInfo = event.target as LoaderInfo;
               loaderInfo.removeEventListener(Event.COMPLETE, loadImageComplete);
            
                var image:Bitmap = loaderInfo.content as Bitmap;
                image.alpha = 0.7;
                image.y = -30;
                addChild(image);
            
                loadSWF();
            
                var text:TextField = new TextField();
                text.selectable = false;
                text.width = 400;
                text.height = 50;
                text.defaultTextFormat = new TextFormat("微软雅黑", 30, 0xffffff, true);
                text.text = "我们爱这片代码爱得深沉。";
                text.x = 100;
                text.y = stage.stageHeight - text.height;
                addChild(text);
        }
        
        /**
         * 加载外部swf资源
         * 
         */
           private function loadSWF():void 
           {
               var loader:Loader = new Loader();
               loader.contentLoaderInfo.addEventListener(Event.COMPLETE, 
               loadSWFComplete);
               var loaderContext:LoaderContext = 
               new LoaderContext(true, ApplicationDomain.currentDomain);
               loader.load(new URLRequest("assets/loaderTest.swf"), loaderContext);
         }
         private function loadSWFComplete(event:Event):void
         {
            var loaderInfo:LoaderInfo = event.target as LoaderInfo;
            loaderInfo.removeEventListener(Event.COMPLETE, loadSWFComplete);
            
            //应用域反射获取素材资源
            var appDomain:ApplicationDomain = ApplicationDomain.currentDomain;
            if(!appDomain || !appDomain.hasDefinition("assets.TreeImage"))
                return;
            var cls:Class = 
            (appDomain.getDefinition("assets.TreeImage") as Class);
            if(!cls)
                return;
            var mc:MovieClip = new cls();
            mc.x = stage.stageWidth - mc.width;
            mc.y = stage.stageHeight - mc.height;
            addChild(mc);
            
        }
    }
}


  LayaFlash IDE运行后:

0.png


2.显示容器

2.1.Sprite

  Sprite是常用的显示容器类,和AS3的Sprite类一样,也支持Event.ENTER_FRAME_EVENT等常用事件和添加其他显示对象。

   使用的时候只要使用new关键字新建一个Sprite的实例,再将调用Sprite对象的addChild把其他显示对象添加到里面即可显示将其他显示 对象作为子显示对象加入其中。它也可以被作为其他显示容器的子显示对象被其他显示容器对象添加。除了addChild方法外,还可以调用 addChildAt、getChildByName等方法,就像使用AS3里的Sprite类一样操作LayaFlash中的Sprite类。

2.2.MovieClip

   LayaFlash的MovieClip是呈现动画的显示类,继承自Sprite类。在LayaFlash中,MovieClip没有时间轴的概念,使用与此 MovieClip对象对应的一系列图片连续渲染形成画面。在Flash CS系列工具中制作好的MovieClip元件,发布成swf资源后要用LayaFlash资源转换工具转换,从原始swf文件中解析出其中包含的所有 图片资源和对应的动画配置数据,再加载到LayaFlash编译的H5项目中使用,加载办法和AS3加载swf文件的操作一样,使用Loader类加载。

  和AS3的MovieClip的不同的地方是,如果这个MovieClip元件是含有帧代码,则必须将帧代码提取出来,保存在一个AS3类文件中,然后将AS3文件存放在和类路径保持一致的项目目录下。下面是提取帧上代码的做法示例。

  示例源码下载:layaFlashMovieClip.rar

  在新建的fla文件里创建一个影片剪辑元件,在元件里制作一段缩放动画:

8.png

  然后在帧上添加一个简单的停止代码“stop()”:

9.png

  给元件添加链接类“asset.Movie”:

10c.png

  Main.as类代码如下:

private function init(e:Event = null):void
{
    removeEventListener(Event.ADDED_TO_STAGE, init);
    
    this.stage.scaleMode = StageScaleMode.NO_SCALE;
    this.stage.align = StageAlign.TOP_LEFT;
    
    IFlash.setSize(550, 400); //2D项目中设置场景尺寸
    IFlash.setOrientationEx(1); //是否为横屏模式
    IFlash.setBgcolor("#000000"); //背景色
    IFlash.showInfo(false); //是否显示帧率
    
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, assetComplete);
    loader.load(new URLRequest("assets/displayContainerAsset.swf"), new LoaderContext(true, ApplicationDomain.currentDomain));
}

private function assetComplete(event:Event):void
{
    var loaderInfo:LoaderInfo = event.target as LoaderInfo;
    loaderInfo.removeEventListener(Event.COMPLETE, assetComplete);
    
    var appDomain:ApplicationDomain = ApplicationDomain.currentDomain;
    if (!appDomain || !appDomain.hasDefinition("asset.Movie"))
    {
        trace("asset.Movie is null.");
        return;
    }
    
    var cls:Class = appDomain.getDefinition("asset.Movie") as Class;
    var movie:MovieClip = new cls();
    addChild(movie);
    movie.play();

}

  LayaFlash编译并运行,发现直接播放的影片剪辑动画没有受帧上的代码“stop()”的控制而停下来,要想MovieClip在LayaFlash中也能和在AS3上运行效果一样,必须新建一个和库中影片剪辑元件的链接类名相同的AS3类“asset.Movie.as”: 

11c.png

  Movie.as的代码:

package asset
{
    import flash.display.MovieClip;
    
    public class Movie extends MovieClip
    {
        public function Movie()
        {
            super();
            
            addFrameScript(24, frame25);
        }
        
        private function frame25():void
        {
            stop();
        }
    }
}

  如果LayaFlash加载了一个主舞台上存在时间轴动画的“swf文件”(注意,这里的swf不是Flash发布的字节码文件,详细解释参见《Flash资源转换工具》的内容),添加到显示对象后,要手动调用play()方法舞台上的时间轴动画才开始播放。


3.矢量处理

  LayaFlash的矢量绘制功能是使用的标准绘图API实现的,但不支持渐变填充方式绘制图形。

  绘制矢量的工作原理也使用了“指令流”的机制,在调用各个绘图API的时候,LayaFlash只向Graphics的“虚拟画布”中添加“指令”,在每帧的渲染流程中进行绘制,与“指令流”和“虚拟画布”相关的内容请参看《LayaFlash显示列表的渲染》教程。

  矢量处理示例源码下载:layaFlashDrawGraphic.rar

3.1直线

1.png

  代码示例

private function drawLine():void
{
    var content:Shape = new Shape();
    content.graphics.lineStyle(5, 0x24B69F, 1);
    content.graphics.moveTo(50, 50);
    content.graphics.lineTo(100, 150);
    content.graphics.lineTo(200, 50);
    
    content.graphics.lineT(50, 50);
    content.x = 50;
    content.y = 50;
    this.addChild(content);
}

3.2.贝塞尔曲线

2.png

  代码示例:

private function drawCurve():void
{
    var content:Shape = new Shape();
    
    content.graphics.lineStyle(5, 0x24B69F, 1);
    content.graphics.moveTo(100, 50);
    content.graphics.curveTo(30, 10, 200, 0);
    
    content.x = 50;
    content.y = 50;
    
    this.addChild(content);
}

3.3矩形

3.png

代码示例:

private function drawRect():void
{
    var content:Sprite = new Sprite();
    content.graphics.lineStyle(2, 0x0, 1);
    content.graphics.beginFill(0x24B69F, 1);
    content.graphics.drawRect(0, 0, 100, 100);
    content.graphics.endFill();
    
    content.x = 50;
    content.y = 50;
    
    this.addChild(content);
}


3.4.圆形

4.png

  代码示例:

private function drawCircle():void
{
    var content:Shape = new Shape();
    content.graphics.lineStyle(2, 0x0, 1);
    content.graphics.beginFill(0x24B69F, 1);
    content.graphics.drawCircle(0, 0, 80);
    content.graphics.endFill();
    
    content.x = 150;
    content.y = 150;
    
    this.addChild(content);
}

3.5弧线

5.png

代码示例:

private function drawRadius():void
{
    var content:Sprite = new Sprite();
    content.graphics.lineStyle(2, 0x24B69F, 1);
    
    var g:Graphics = content.graphics;
    for (var i:int = 0; i <= 90; i++)
    {
        var lx:Number = 100 * Math.cos(-i * Math.PI / 180);
        var ly:Number = 100 * Math.sin(-i * Math.PI / 180);
        (i == 0) && g.moveTo(lx, ly);
        g.lineTo(lx, ly);
    }
    
    content.x = 150;
    content.y = 150;
    
    this.addChild(content);
}


4.遮罩处理

  LayaFlash实现遮罩的类是一个名叫ClipDraw的类,与其说是实现,不如说它提供了一个能编译成JS文件后调用JS代码的接口类。为了保证性能,LayaFlash项目只支持使用矩形遮罩特效。

  下面是加载并显示一张图片的代码片段:

private function init(e:Event = null):void
{
    removeEventListener(Event.ADDED_TO_STAGE, init);
    
    this.stage.scaleMode = StageScaleMode.NO_SCALE;
    this.stage.align = StageAlign.TOP_LEFT;
    
    IFlash.setSize(550, 400); //2D项目中设置场景尺寸
    IFlash.setOrientationEx(1); //是否为横屏模式
    IFlash.setBgcolor("#000000"); //背景色
    IFlash.showInfo(false); //是否显示帧率
    
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, 
    layaImageLoadComplete);
    loader.load(new URLRequest("laya.png"));
}

private function layaImageLoadComplete(event:Event):void
{
    var loaderInfo:LoaderInfo = event.target as LoaderInfo;
    loaderInfo.removeEventListener(Event.COMPLETE, 
    drawCallbackTestImageComplete);
    
    var content:Sprite = new Sprite();
    content.addChild(loaderInfo.content);
    content.x = 100;
    content.y = 100;
    this.addChild(content);
}

  在LayaFlash运行的效果:
6.png

  我们修改代码使用遮罩让程序只显示图片的右下角部分内容,修改layaImageLoadComplete方法的代码

private function layaImageLoadComplete(event:Event):void
{
    var loaderInfo:LoaderInfo = event.target as LoaderInfo;
    loaderInfo.removeEventListener(Event.COMPLETE, layaImageLoadComplete);
    
    var content:Sprite = new Sprite();
    content.addChild(loaderInfo.content);
    content.x = 100;
    content.y = 100;
    this.addChild(content);
    
    var mask:Shape = new Shape();
    mask.graphics.lineStyle(1);
    mask.graphics.beginFill(0x0);
    mask.graphics.drawRect(0, 0, content.width, content.height);
    mask.graphics.endFill();
    mask.x = content.x + content.width / 2;
    mask.y = content.y + content.height / 2;
    content.mask = mask;
}

   代码新建了一个Shape对象,在里面绘制一个矩形,并设置到content的mask属性上,运行后的效果:
7.png


5.九宫格缩放处理

  LayaFlash使用的九宫格元件也需要在Flash CS系列工具制作,不同的是,在Flash CS中对元件启用“九宫格缩放”设置后,无需再将图片分成9个部分,我们只要保持完整素材在一个图层上就好。然后用LayaFlash的资源转换工具将Flash发布的swf文件转换成LayaFlash所需的素材即可(包含一个与swf文件同名的文件夹和一个被重新生成的同样是swf后缀的文件)。如何使用LayaFlash的资源转换工具,请参看《Flash资源转换工具》教程的内容。

  Flash、LayaFlash九宫格缩放元件的制作差异示例源码下载:layaFlash9SliceScaling.rar

  Flash中的九宫格缩放设置方法:

12c.png

  LayaFlash中使用的九宫格缩放制作方法:

13c.png

  以上两个元件在库中设置的链接类名分别为“Flash9SliceScalingImage”和“Laya9SliceScalingImage”。下列代码展示了使用九宫格缩放的用法:

private function test9SliceScaling():void
{
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoadComplete);
    loader.load(new URLRequest("layaFlash9SliceScaling.swf"), new LoaderContext(true, ApplicationDomain.currentDomain));
}

private function swfLoadComplete(event:Event):void
{
    var loader:LoaderInfo = event.target as LoaderInfo;
    loader.removeEventListener(Event.COMPLETE, swfLoadComplete);
    
    var appDomain:ApplicationDomain = ApplicationDomain.currentDomain;
    if (!appDomain || !appDomain.hasDefinition("Flash9SliceScalingImage"))
        return;
    var cls:Class = (appDomain.getDefinition("Flash9SliceScalingImage") as Class);
    if (!cls)
        return;
    var mc:MovieClip = new cls(); //原Flash方式制作的九宫格缩放元件
    mc.scaleX = 0.7;
    mc.scaleY = 0.9;
    mc.x = 50;
    mc.y = 50;
    this.addChild(mc);
    
    cls = (appDomain.getDefinition("Laya9SliceScalingImage") as Class);
    if (!cls)
        return;
    mc = new cls(); //LayaFlash方式制作的九宫格缩放元件
    mc.scaleX = 0.7;
    mc.scaleY = 0.9;
    mc.x = 150;
    mc.y = 50;
    this.addChild(mc);
}

  LayaFlash IDE编译并运行后:

14.png

  图中的两个元件分别是使用原版Flash方式和LayaFlash的方式制作的九宫格缩放元件,两种方式制作出的元件效果一致,但LayaFlash比原版方式更简便。但右侧元件的制作方式在AS3下不适用。