Flash Player如何加载主SWF文件?

5

更新:

似乎每个人都没有仔细阅读我的问题,所有答案都建议我预加载或使用外部资源。所以任何愿意回答的人,请注意本帖中加粗的问题。谢谢!


我正在开发一个简单的Flash应用程序,只有一个SWF文件。我希望SWF动画尽快开始播放,因此我不会为它构建预加载器。如果我的ActionScript代码引用尚未加载的资源会发生什么情况?

例如,当电影已经加载到第10帧时,该代码将导致播放头从第1帧跳到第20帧。 在这种情况下,Flash播放器会怎么做?

  • 阻止脚本执行,停止播放,继续从第11帧到第20帧进行加载(不执行脚本),在加载完成后跳转到第20帧并调用该帧上的脚本?
  • 阻止脚本执行,停止播放,忽略加载第11帧到第19帧,加载第20帧,跳转到第20帧并调用该帧上的脚本?
  • 忽略跳转到第20帧,在执行跳转到第20帧语句后继续执行下一个语句?
  • 还是其他什么?

如果Flash播放器不忽略跳转到第20帧,则在完全加载第20帧时触发任何事件吗?

注意:对于第一个问题的答案应该专注于我的示例,涵盖所有情况(例如从库中附加电影...)更好,但不是必需的。

谢谢!


如果您想精细调整加载体验,请不要依赖Flash的自动加载机制。也不要使用框架。使用类似于BulkLoader这样的工具来加载资源。您的.swf文件应仅包含需要在第一帧上显示的资产和所有代码。 - sydd
5个回答

3

Flash总是会在运行应用程序之前加载所有帧,但是帧内容可能没有完全加载。因此,如果您在第20帧上有一些图片,则可能不会出现。

但基本上您不应该依赖Flash为您加载资源 - 它可能按您想要的顺序进行加载,但也可能不会。如果您有许多资源并且要跳转到不同的帧中,则应使用Loader类自己处理加载。


由于某些原因,我不想在播放影片之前完全加载它,或者在需要时加载外部资源。 - ExpExc
2
@ExpExc,这有点矛盾。您既不想加载所有内容,也不想按需加载。那么您想如何处理加载资产? - laurent
1
我不记得在文档中看到过这方面的内容。我的猜测是,当你到达帧时,资产是否会被加载还是未定义的。这可能取决于SWF的编译方式,添加资产的顺序,互联网连接速度等等。唯一让事情按照你想要的方式加载的方法是通过代码加载它们。 - laurent
@ExpExc,我相信这是默认的加载方法,即当需要显示某些内容时,就会开始加载(当然,前提是该资源未嵌入)。 - Pranav Hosangadi
@Laurent,你的意思是“Flash在运行应用程序之前总是会加载所有帧”吗? - user963395
显示剩余2条评论

1

Flash播放器将尝试跳转到第20帧。但它只能到达已加载的帧。因此,如果您告诉它去到20,而只有10个被加载,那么您将会到达第10帧。

在代码中调用未加载的资源将会抛出错误或将该对象定义为空值。不用说,这需要避免。首先加载这些资源。

一个好的解决方案是使用-frame编译器参数创建一个2帧的Flash动画。第一帧包含预加载器,第二帧包含完整的应用程序。这样,在调用完整功能之前,您可以预加载所需内容。

以下是如何实现的示例。

package 
{
    import flash.display.DisplayObject;
    import flash.display.MovieClip;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.utils.getDefinitionByName;

    /**
     * ...
     * @author Zachary Foley
     */
    public class Preloader extends MovieClip 
    {

        public function Preloader() 
        {
            if (stage) {
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
            }
            addEventListener(Event.ENTER_FRAME, checkFrame);
            loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
            loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);

            // TODO show loader
        }

        private function ioError(e:IOErrorEvent):void 
        {
            trace(e.text);
        }

        private function progress(e:ProgressEvent):void 
        {
            // TODO update loader
        }

        private function checkFrame(e:Event):void 
        {
            if (currentFrame == totalFrames) 
            {
                stop();
                loadingFinished();
            }
        }

        private function loadingFinished():void 
        {
            removeEventListener(Event.ENTER_FRAME, checkFrame);
            loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);
            loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError);

            // TODO hide loader

            startup();
        }

        private function startup():void 
        {
            var mainClass:Class = getDefinitionByName("Main") as Class;
            addChild(new mainClass() as DisplayObject);
        }

    }

}

要使用此功能,您需要将frame参数添加到您的构建中。对于此示例,frame参数应为:

-frame start Main

正如我所提到的,我不想使用预加载程序。无论如何,感谢您的回答。 - ExpExc
欢迎。但请将“preloader”一词视为“可以在未预载资源的情况下播放的swf部分”——它不必是无聊的百分比计数器。如果您不想出现错误,那么您需要某种有效地执行preloader功能的东西,无论它是否看起来像传统的preloader。 - Plastic Sturgeon
我绝对理解在代码引用资源之前必须要有可用资源这一事实。我只是不想连续逐帧加载,但据我所知,Flash 不允许按需加载所需的帧。我在之前的评论中提到的“ Preloader ”意味着像您的代码一样在完全加载之前进行加载。这可能会让用户感到沮丧,因此我的解决方案现在是轮询并等待帧加载完毕后再转到该帧。 - ExpExc
我已经进行了一些测试,结果如你所指出:Flash播放器将尝试跳转到第20帧。但它只能到达已加载的帧。给你点赞。 (请阅读我的答案以获取详细信息) - ExpExc

0

在您的情况下,您需要为您的项目定义渐进式加载方法。

首先开发外部资源,最初只加载一个并显示它。只需开始第二个加载并使用已加载的UI管理显示即可。这样,您就可以避免预加载程序。当您获得已加载项目列表后,只需逐个以渐进方式进行显示。

首先仅显示一个。 第二次加载后,显示第一和第二个... 然后依此类推,您需要进行管理

否则,您必须等待第一个显示,直到下一个显示资产加载完成。这次不要显示预加载程序。


0

我使用Adobe Flash Professional进行了一些测试,以找到我的问题的答案。任何感兴趣的人都可以通过在Adobe Flash中执行以下步骤来重现测试:

  1. 创建一个电影,其中包含一些帧,每个帧都包含一个图像和一些ActionScript代码。
  2. 选择菜单控制 -> 测试电影 -> 在Flash Professional中:将显示调试播放器
  3. 在调试播放器中,选择菜单查看 -> 下载设置,然后选择所需的下载速度
  4. 还要在调试播放器中,确保带宽分析器模拟下载视图菜单下被选中。

如果脚本不改变播放头,则Flash播放器将:

  1. 加载第1帧并等待其完全加载
  2. 转到第1帧
  3. 执行第1帧上的脚本
  4. 显示第1帧
  5. 对于第2帧及更高帧,执行以上步骤...(停留在第1帧,直到第2帧完全加载,然后转到第2帧,执行脚本,显示...)

如果脚本改变了播放头,例如从第1帧跳到第20帧,Flash播放器将会:

  1. 继续执行第1帧中的所有脚本语句(即使这些语句在跳转语句之后),并显示第1帧。
  2. 如果第20帧已经加载,则跳转到第20帧,在其上执行脚本并显示它。如果没有加载,则跳转到最近已加载的帧(在我的问题示例中是第10帧),但不要在该帧上执行脚本。

0
在AS2中,尝试使用以下代码。加载进度将显示在第一帧,主要内容将在第三帧显示。 此代码在ActionScript 2.0参考(getBytesLoaded)中。http://help.adobe.com/ko_KR/AS2LCR/Flash_10.0/00001304.html#1333866
if (this._framesloaded<this._totalframes) {
    this.gotoAndPlay(1);
} else {
    this.gotoAndStop(3);
}

在AS3中,使用This。

this.loaderInfo.addEventListener(Event.COMPLETE, completeHandler);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接