日期:2014-05-16  浏览次数:20397 次

AS3和JS互相调用的小技巧【二】
引用
AS3和JS的互相调用网上一搜能搜到很多,我确实也是这么做的。然而结果却并非令人满意,大部分都是抄子chm帮助手册,或者是叙述得不明白。于是我又手痒了,写篇详细易读的出来,连带分享一个防止缓存的小技巧。

在这里我要先描述一下功能的需求:写死swf文件,读取xml的配置信息,仅靠修改页面上的js代码来改动所需要的xml文件url,并防止缓存。

---

第一步,建立flash as3文件,之后它就不需要改动了,只要编写它的文档类并发布就行。这里我将.fla文件命名为Test.fla,文档类关联为Test.as。

首先我们来展示下AS3中调用JS的方法,这是最简单的事情,简单到只需一句话便可。

AS3的Test.as文档类:

package {
  import flash.display.Sprite;
  import flash.external.ExternalInterface;
 
  public class Test extends Sprite {
    public function Test() {
      callJavaScriptFunction();
    }
   
    private function callJavaScriptFunction():void {
      if(ExternalInterface.available) {
        ExternalInterface.call("sayHello", "army");
      }
    }
  }
}


发布页面中的JS代码:

function sayHello(name) {
  alert("hello, " + name);
}


as代码很简单,文档类Test继承Sprite,构造函数中执行定义的callJavaScriptFunction()方法。先要说明下ExternalInterface这个类,它在flash.external包下,官方的解释是“在 ActionScript 和 Flash Player 的容器之间实现直接通讯的应用程序编程接口,例如,含有 JavaScript 的 HTML 页。”,可以说是标准的通信接口,只要是和JS互相调用,都要用到它。

在callJavaScriptFunction()方法中,先是判断ExternalInterface.available属性,当外部接口可调用时,执行ExternalInterface类的call方法,它接收若干个参数。第一个是调用的js方法名,后面依次是传给所调用js方法的参数。在这里ExternalInterface.call("sayHello", "army")就相当于执行了js代码中的sayHello("army")方法。如你所见,页面中的确弹出了一个窗口,内容正是传过来的"army"。

需要注意的是,js代码段必须写在嵌入的swf段前面,因为这样才能确保执行之前js全部载入了,否则的话可能会出现无法执行的情况。

---

接下来我们来看看从JS中调用AS的方法。这里我先提个问题:由于放在网络上,swf文件的下载时间是个未知数,如何才能确保js调用as的时候swf已经加载完成了呢?

我所使用的是一个小技巧:依旧是js片段写在swf前面,先在swf里面调用js方法,然后所调用的js方法里再返回去调用as的方法。这样就可以确保swf加载完成并能顺利执行了,整个过程如下:

js片段首先被浏览器读取并加载 =》 浏览器读取swf文件直至完成 =》 swf调用js的方法 =》 被调用的js方法中去调用swf中的as方法。

AS3的Test.as文档类:

package {
  import flash.display.Sprite;
  import flash.external.ExternalInterface;
  import flash.text.TextField;
 
  public class Test extends Sprite {
    public function Test() {
      callJavaScriptFunction();
    }
   
    private function callJavaScriptFunction():void {
      if (ExternalInterface.available) {
        ExternalInterface.addCallback("callAsFunction", onCallBackHandler);
        ExternalInterface.call("callBackBridge");
      }
    }
   
    private function onCallBackHandler(s:String):void {
      var textField:TextField = new TextField();
      textField.text = s;
      addChild(textField);
    }
  }
}


发布页面中的JS代码:

function getSwfInstance(movieName) {
  if (navigator.appName.indexOf("Microsoft") != -1) {
    return window[movieName];
  } else {
    return document[movieName];
  }
}
function callBackBridge() {
  getSwfInstance("Test").callAsFunction("Hello, army!");
}


页面html代码:

<noscript>
  <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="725" height="350" id="VideoCenter" align="center">
  <param name="allowScriptAccess" value="sameDomain" /&g