actionScript 3.0与javascript通信

一.JavaScript调用ActionScript公开的方法

在Flex中通过ExternalInterface调用addCallback()来将AS的一个方法注册为一个JS和VBScript可以调用的方法。
函数如下:
addCallback(function_name:String, closure:Function):void
function_name就是Flex对外部展示,能够被JS调用的函数。
closure是Flex中AS写的函数

as:

<?xml version="1.0" encoding="utf-8"?>    

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"          

     creationComplete="initApp()">    

     <mx:Script>    

         <![CDATA[    

 

             import flash.external.*;                   //引入ExternalInterface 

             public function myAsFuncn(js:String):String    

             {    

                 return  "js:"+js+"访问了 as:"+asInput.text;    

             }    

 

             public function initApp(): void{

				   ExternalInterface.addCallback("myAsFuncn",myAsFuncn);    

	    }

 

         ]]>    

     </mx:Script>  

     <mx:TextInput  id="asInput"/>             

</mx:Application>

js:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="UTF-8">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta http-equiv="Content-Language" content="UTF-8" />

 

 

    <head>  

 

		<script src="swfobject.js" type="text/javascript"></script>

		<script src="jquery.js" type="text/javascript"></script>

 

        <script  type="text/javascript" >     

 

			//var swf = new swfobject("FlexDemo003.swf", "myFlexFun", "300px", "200px", "9.0.0","expressInstall.swf", flashvars,params);

			//swf.write("myFlexFun");

			var flashvars = {};

			var params = {menu: "false",wmode:"opaque"};

			swfobject.embedSWF("FlexDemo003.swf", "myFlexFun", "300px", "200px", "9.0.0","expressInstall.swf", flashvars,params);

 

 

             function callAs()    

             {    

                var myFlexfun = findSWF("myFlexFun");    

                var result = myFlexfun.myAsFuncn("点我看效果按钮");    

                alert(result);    

             }  

 

			 function findSWF(movieName) {   

				   if (navigator.appName.indexOf("Microsoft")!= -1) {   

					   return window[movieName];   

				   } else {   

					   return document[movieName];   

				   }

			  }

 

       </script>  

   </head>  

 

 

   <body>  

 

	<div id="myFlexFun"></div>

        <input type="button" value=" 点我看效果" onclick="callAs()" />

 

  </body>  

</html>

二.ActionScript调用JavaScript方法

call(ExternalInterface.call 方法)
public static call(methodName:String, [parameter1:Object]) : Object
参数
methodName:String ― 要在容器中调用的函数的名称。如果该函数接受参数,则这些参数必须显示在 methodName 参数后面。
parameter1:Object [可选] ― 要传递到该函数的任何参数。您可以指定零个或多个参数,参数之间用逗号分隔。此参数可以是任何 ActionScript 数据类型。当调用 JavaScript 函数时,ActionScript 类型自动封装到 JavaScript 类型中。当调用某个其它 ActiveX 容器时,将在请求消息中对参数进行编码。
返回
Object ― 从容器接收的响应。如果调用失败(例如,当容器中没有这种函数时、接口不可用时、发生递归时,或出现安全问题时),则返回 null。

js:

    <html>  

    <head>  

        <script language="JavaScript" type="text/javascript">  

         //无参数 

        function myJsFunctionNoPara() {  

             alert("as 调用 js了");  

        }  

        //有参数 

         function myJsFunctionHavePara(p) {  

            alert(p);  

        }  

      </script>  

  </head>  

   <body>  

       <object id="myFlexFun" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"  

           width="250" height="300">  

           <param name="movie" value="AS2JS.swf" />  

           <param name="quality" value="high" />  

           <embed src="AS2JS.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer"  

               type="application/x-shockwave-flash" width="250" height="300"></embed>  

       </object>  

  </body>  

   </html>

as:

    <?xml version="1.0" encoding="utf-8"?>    

    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">    

       <mx:Script>    

            <![CDATA[    

 

                private function callNoParaJavaScript():void {  

                    ExternalInterface.call("myJsFunctionNoPara");  

                    }   

                private function callHaveParaJavaScript():void {  

                   ExternalInterface.call("myJsFunctionHavePara","as 调用js了");  

                    }   

 

           ]]>    

       </mx:Script>  

       <mx:Button label=" 调用无参数js:Say 'as 调用js了'"  click="callNoParaJavaScript();" />   

       <mx:Button label="调用有参数js:Say 'as 调用js了'"  click="callHaveParaJavaScript();" />        

   </mx:Application>

3.调用内置js函数

    ExternalInterface.call("alert", "Hello World, from ActionScript");  

    ExternalInterface.call("eval", "alert('OK')");

三.常见问题

1.ExternalInterface.addCallback参数

JavaScript 跟 ActionScript 3.0 交互也是通过 flash.external.ExternalInterface 这个类,不过与跟 Flash 8 中跟 ActionScript 2.0 交互所使用的 flash.external.ExternalInterface 还是有所不同的。最大的不同就是 ExternalInterface.addCallback 方法在 ActionScript 3.0 中只有 2 个参数了,而不再有 instance 这个参数。

2.avaScript 调用 Flash 中的 ActionScript3.0提示方法不存在

这个问题是跟 Flash 中执行 ExternalInterface.addCallback 的时间有关的,ExternalInterface.addCallback 必须要在 HTML 的完全载入之后也就是 window.onload 事件执行后才可以执行,否则,它所发布的方法都无法在 JavaScript 中调用。

解决方法:在 Flash 9 的 ActionScript 3.0 帮助中有个例子,里面包含了这个解决方法,就是首先在 js 中设置两个标志,例如 jsReady 和 swfReady 这两个变量作为标志,开始都设置为 false,当 window.onload 时,设置 jsReady 为 true,在 Flash 中一开始检查 JavaScript 中的这个 jsReady 标志是否是 true(通过 ExternalInterface.call 方法调用 JavaScript 中的返回这个标志的一个函数),如果不为 true,就设置一个定时器,经过一段时间后(例如 50 或 100 毫秒)重复这个检查这个标志,一旦为 true,则执行 ExternalInterface.addCallback 来发布 ActionScript 要提供给 JavaScript 调用的函数或方法,执行完所有的 ExternalInterface.addCallback 后,通过 ExternalInterface.call 方法调用 JavaScript 中的设置 swfReady 标志的函数设置 swfReady 为 true。之后,当 JavaScript 检测到 swfReady 为 true 后,再调用 ActionScript 中的方法就不会遇到上的说的这个问题了。

如果简单一点的调用这样还可以,如果是有好多这样的调用就比较麻烦了。我是通过建立两个执行队列:jsTaskQueue 和 swfTaskQueue,当在 jsReady 为 true 之前,如果有要调用 ActionScript 的操作,就把这个操作放到 jsTaskQueue 中,当 js 在 window.onload 中执行设置 jsReady 时,把这个队列中的任务取出来执行,当 jsReady 为 true 后 swfReady 为 true 之前,如果有要调用 ActionScript 的操作,就把这个操作放到 swfTaskQueue 中,当 ActionScript 通过 ExternalInterface.call 方法调用 JavaScript 中的设置 swfReady 标志的函数设置 swfReady 为 true 时,把这个队列中的任务取出来执行。当 jsReady 和 swfReady 都为 true 时,那么如果有要调用 ActionScript 的操作,直接运行就可以了。通过这种方法把这些任务封装后,使用这些封装之后的操作,在编写代码就可以按照顺序(而不是异步)来写了,执行时也是顺序执行啦。

3. 在IE中用JavaScript 动态创建的 Flash 标签的问题

如果你是通过 JavaScript 动态创建的 Flash 标签然后插入到 html 中的话(例如通过 innerHTML 赋值的方法或者 appendChild 的方法),很可能你这个操作是在 window.onload 之后才进行,在这种情况下,其它浏览器可以正常进行 JavaScript 和 ActionScript 3.0 的交互,IE 就不行。所以,为了保险,最好的方法就是直接把 flash 标签的 html 写在 html 的 body 中,或者用 JavaScript 的 document.write 来写入 html 的 body 中,后面这种方法对于 IE 来说更合适一些,因为这样的话,可以不需要点击激活 Flash。

4. 在IE中 as发布方法名问题

不要在 ActionScript 3.0中发布名字为 invoke 的方法,否则在 IE 中,JavaScript 调用该方法时会出错。

5.在ie中flash在form的位置

不要把 flash 放到 form 中,否则在 IE 中,JavaScript 调用 ActionScript 时会出错。当然,网上也给出了一个解决这个问题的脚本,不过那个貌似是针对 Flash 8 的 ActionScript 2.0 的,我没有试过,不知道对

ActionScript 3.0 是否同样有效。

6.方法参数包含转移符号的问题

如果在 ActionScript 中通过 ExternalInterface.call 调用 JavaScript 时,参数中如果含有转义字符(\)和特殊字符(\n,\r等)就可能出错。因为在ActionScript和JavaScript中都将“\”作为转义字符,这里的”\\”在程序执行时实际上就是一个[\].

解决办法1:如要传递的数据是 data,将它进行一次 data.replace(/\\/, “\\\\”) 替换之后,在传递给 JavaScript 就可以了。

解决办法2:js和as中有现成的两个全局函数:escape()和unescape()。在调用函数和函数返回前escape一下,接收到参数和函数返回值后再unescape一下就可以了。

as:

   var str:String = "\n\r123\\abc";    

   str = escape(str); // encode 

   var jsret:Object = ExternalInterface.call("jsfun", str);  

 

    if (jsret is String) {  

 

       jsret = unescape(jsret as String); // decode 

 

      Alert.show(jsret.toString());  

 

   }

js:

   function jsfun(str) {    

       str = unescape(str); // decode 

       str += "from js";  

       str = escape(str); // encode 

       return str;  

   }

你可能感兴趣的:(actionscript)