轉載:js和as間的交互

轉載一:javascript

說起AS3與外部腳本的交互,筆者認爲能夠總結成兩種。一是AS3調用外部函數,二是外部腳本調用AS3函數。無外乎就 這兩種。在調用函數的同時,咱們還能夠向函數傳遞一些參數。這就達到了傳遞數據的目的。舉一個最簡單的例子。咱們平時在網絡上看視頻的時候,這些用AS3 製做的播放器就是由外部腳本(多是JS,也多是ASP或其餘腳本)傳遞給它的視頻地址。從而就簡化咱們的後臺程序。有的人會問!你用播放器去讀取外部 的XML數據不是也能夠嗎?確實,當時,當你有成千上萬個視頻的時候,你不可能輸入這麼多數據。一是比較麻煩,二來是影響了網頁運行的速度。因此,AS3 與外部腳本進行交互是很是重要的。css

      其 實,咱們作的絕大多數帶有交互性的FLASH程序都要多多少少與後臺的其餘語言進行交互。這裏,咱們就以JS腳原本舉例說明交互的過程。固然,AS3與 JS腳本能夠說有血緣關係,具體的你們能夠去查看一下FLASH的發展歷史。好了!廢話很少說,咱們這就開始講如何讓JS與AS3進行一些信息的交換。本 節中,咱們只講解JS調用AS3中的函數。反向的調用咱們將在下一節中進行講解!html

       首先,咱們新建一個FLASH文檔,而後在舞臺上繪製一個動態文本,該文本的實例名稱爲wen_txt。好了!美工的部分就算完成了(咱們這裏是一個很是簡單的實例,不要求太複雜。力求突出重點)!java

       現 在,咱們要在FLASH中創建一個容許被外部調用的函數。那麼如何去創建聲明這樣一個函數呢?咱們要使用到一個類,這個類的名字就是 ExternalInterface。不少人都沒有太注意過這個類。這個類其實是在flash.external 包中。這個包是專門用來和外部容器進行通訊的。那麼對這個ExternalInterface類,它的官方解釋是「ExternalInterface 類是外部 API,在 ActionScript 和 Flash Player 的容器之間實現直接通信的應用程序編程接口,例如,含有 JavaScript 的 HTML 頁。」很顯然,這裏已經提到了JS。好了!下面咱們就來寫一下腳本吧!以下:ajax

ExternalInterface.addCallback("abcd",yun);
function yun(zi:String):void{
wen_txt.text = zi;
}chrome

       我 們看,創建一個能夠被外部調用的函數實際上就是使用了 ExternalInterface類的addCallback方法。咱們能夠從宏觀上這樣理解。但實際上它的真正做用是將一個函數註冊爲可從容器調用。 實際上咱們的FLASH端就這麼簡單。好了!保存文件,發佈。注意!這裏,我發佈出來的SWF文件的文件名是ab.swf。編程

       上面咱們已經將FLASH端的腳本寫好了,下面咱們來編寫JS代碼,其實也是一個HTML網頁代碼,這個HTML代碼中包含JS代碼!以下:跨域

<!-- saved from url=(0014)about:internet -->
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>FLASH與JS交互</title>
<script language="JavaScript">
     function pageInit() { 
        sendToActionScript("你好");
     }
     function sendToActionScript(value) { 
         window.ExternalInterfaceExample.abcd(value);
     }
</script>
</head>
<body onload="pageInit();">
     <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
             id="ExternalInterfaceExample" width="500" height="500"
             >
         <param name="movie" value="ab.swf" /> 
     </object>
</body>
</html>瀏覽器

       好了!如今將這個網頁保存到和ab.swf同一文件夾下,而後運行這個網頁。當程序運行的時候,咱們就能夠看到FLASH中的動態文本會出現「你好」字樣!這個過程就是JS調用AS3函數,同時向FLASH傳遞了一個參數,或者說傳遞了一組數據。緩存

       關於這段JS代碼,咱們就很少說了。由於涉及到不少JS腳本的只是。你們能夠在網上查找相關的資料,就能夠明白這段JS腳本的含義了!

       本節咱們就講解到這裏,下一節咱們講解,FLASH如何向JS傳遞參數!

書接上文,上次咱們講到JS向FLASH傳遞參數。本節咱們來說解FLASH向JS傳遞參數。

       先 說說原理吧。實際上咱們所瀏覽的每個網頁均可以看做是一個容器。那何爲容器呢?說白了就是一個盒子。在這個盒子裏面放着許多東西,包括網頁中的文字,圖 片,FLASH,腳本,按鈕,文本框等。因此,咱們的 FLASH若是想訪問網頁中的JS函數,實際上就是訪問上一級中的函數。這種操做相對就要簡單一些。由於咱們的JS函數對網頁中的成員都是公開的,這個網 頁中的任何元素都可以調用這個JS函數。一樣,FLASH也擁有這樣的權限。那麼好了!咱們來看看在網頁中具體是怎樣作的。

        咱們此次先來寫網頁代碼,由於網頁這邊是接受端。代碼以下:

<!-- saved from url=(0014)about:internet -->
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>FLASH與JS交互</title>
<script language="JavaScript">
     function sendToJavaScript(value) {
         document.forms["form1"].output.value += "\n" + "ActionScript says: " + value;
     }
</script>
</head>
<body>
     <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
             id="ExternalInterfaceExample" width="500" height="500"
             >
         <param name="movie" value="ab.swf" /> 
     </object>
     <form name="form1" onsubmit="return false;">
         <textarea cols="60" rows="20" name="output" readonly="true">Initializing...</textarea>
     </form>
</body>
</html>

       具 體的什麼意思筆者在這裏就很少說了,屬於JS方面的知識,你們能夠去查看相關資料。好了下面就是FLASH端的代碼了!咱們先來作美工界面。畫一個輸入文 本,實例名爲wen_txt,再作一個影片剪輯元件,實例名爲 an_mc。好了!美工部分作完了!咱們來寫腳本。以下:

an_mc.addEventListener(MouseEvent.CLICK,chuan);
function chuan(evt:Event):void {
ExternalInterface.call("sendToJavaScript", wen_txt.text);
}

       咱們看,其實在FLASH中調用外部的JS函數仍是用到了ExternalInterface類。而此次咱們是使用的call方法。

       好了!運行網頁,咱們在FLASH的輸入文本中輸入一串文字,而後按一下按鈕。以後這段文字就會出如今網頁的文本框裏面!

       你們能夠本身動手作一次,體會一下FLASH向JS傳遞參數的過程!

 

js與as3相互通訊、調用問題

(

這幾天在學FLASH的AS3編程,以爲挺有意思的。之前以爲FLASH與AS3的相互調用很神奇,如今一看,仍是挺簡單的,吧代碼貼上來。

AS代碼:

import flash.external.ExternalInterface;

ExternalInterface.call("jscall",'abc'); //as調用JS方法,jscall爲js的函數名,後面的爲參數,能夠傳遞多個參數

txt.text = 'text2';

ExternalInterface.addCallback("jscallfun",getASFun); //提供給JS調用的AS方法

function getASFun(value:String):void {

   txt.text = value;  

}  

 

 

HTML部分:

<script language="javascript">

function thisMovie(movieName)

{  

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

   {  

      return window[movieName];  

   }

   else

   {  

      return document[movieName];  

   }  

}

window.onload = function(){ //此行代碼必不可少,若是不用此事件,因爲打開頁面後,FLASH加載須要時間,可能FLASH尚未加載進來就已經執行到此函數了,從而致使調用失敗

thisMovie("FlashID").jscallfun('中國');

}

//alert(thisMovie("FlashID"));

 

function jscall(str)

{

   alert(str);

}

 

</script>

<object id="FlashID" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="800" height="800">

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

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

   <param name="swfversion" value="8.0.35.0" />

   <param name="allowScriptAccess" value="always" />

   <param name="wmode" value="transparent" />

   <embed src="test1.swf" quality="high" wmode="transparent" width="800" height="800" name="FlashID" align="middle" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"/>

</object>

網頁JS調用FLASH 小教程  

在網頁上用JS調用FLASH程序,好比一個視頻網站,按照動態服務器程序產生一個URL,點擊後,能夠在預先製做完成 的FLASH 播放器來播放.此次的小教程,只是簡單的講下,用JS調用AS程序,其實FLASH 8在這方面的資料不少.忽然發現,從FLASH 2004到FLASH 8,FLASH資料多了不少啊.不過咱們此次是說FLASH CS3,於時俱進嘛.

     首先,咱們先打開FLASH製做接受端口程序來監聽JS發送的事件:(咱們此次的目的是發送一組字符,很簡單的,若是往復雜了作,也是一樣的道理)

     在FLASH CS3舞臺上隨便放個動態文本,把實例命名:astxt.接着輸入代碼:

//用ExternalInterface.addCallback來接受網頁上用JS寫的JsFunction程序,而beCalled是說明FLASH在

//接收到JS的時候,所發生的事件.

ExternalInterface.addCallback("JsFunction",beCalled);

//txtVar是從JS程序傳送過來的變量.

function beCalled(txtVar):void {

 astxt.text = txtVar;

}

下面是在網頁中寫的代碼,爲了簡化代碼,我這裏就寫主要的幾個地方.首先在FLASH下面插入一個

<div>

<form name="jsForm">

           <input type="text" size="10" value="你好" name="texts"></input>

           <input type="button" value="點我啊"

           <!-- 下面的代碼就是點擊網頁上的代碼後,所調用的程序,注意這個程序叫"callAS3"是放在

 <head></head>以內的.document.jsForm.texts.value就是須要傳遞的變量

 -->

           onclick="callAS3(document.jsForm.texts.value)">

</form>

</div>

在以內寫上網頁按鈕點擊後所調用的程序.

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

 function callAS3(varText){

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

                                 //大家可看到JsFunction就是FLASH程序裏監聽的程序.而JsToAs就是我產生

                      //的SWF的名字,varText那就是變量參數拉.

           JsToAs.JsFunction(varText);

   }

   else{

                          window.document.JsToAs.JsFunction(varText);

   }

 }

</script>

    看,這就完成了用JS來調用FLASH.你能夠在網頁裏的input裏寫入幾個字符,點擊按鈕後,FLASH裏的TEXT裏就會出現你在網頁上所輸入的字符.

---------------------------------------------------------------------------

    反過來,如何用FLASH裏的程序調用JS呢?也簡單在剛纔的FLASH裏繼續寫.

//在舞臺上放一個Button,命名爲:btn.

btn.addEventListener(MouseEvent.CLICK, clickHandler);

function clickHandler(e:MouseEvent):void {

             //asFunction就是咱們要在網頁裏寫的程序.

 ExternalInterface.call("asFunction","哈哈,我是來自FLASH");

}

//按鈕點擊後,就會把"哈哈,我是來自FLASH"這句話傳遞到網頁裏.你能夠在網頁裏創建一個TEXT來接收

//這個參數.;

[code]

在網頁裏的<body></body>以內寫上

<form name="form2">

    <input type="text" size="10" name="accept"></input>

</form>

在網頁的<head></head>裏寫上

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

 function asFunction(varText) {

       document.form2.accept.value= varText;

 }

</script>

OK,這樣網頁 就能夠從FLASH接受參數,或者由FLASH來調用外部的JS.

 

 

 

 

 

轉載二:     

 

不論是as調用js,仍是js調用as,其實都圍繞ExternalInterface。ExternalInterface 類是外部 API,這是一個在 ActionScript 和 Flash Player 容器之間實現直接通訊的應用程序編程接口。固然插入flash的html標籤中<param name='allowScriptAccess' value ='always' /> 不能爲never,若是設置成never一下全部都是空談了,通常狀況下都設置成always,它也能夠接受具體的domain或者IP。
     ExternalInterface有兩個提供相互調用的靜態方法:

     /**
      * @param functionName {String} 
      * @param closure {Function}
      * @usage 將 ActionScript 方法註冊爲可提供外部js調用。
      */
     addCallback(functionName:String, closure:Function):void 

     /**
      * @param functionName {String} 
      * @param arguments {Function} (optional)
      * @usage 調用頁面上的js。
      */
     call(functionName:String, ... arguments):*

 

Example 1:
假如頁面上有一個叫sayHi的js函數, 以下:

window.onload=function (){
     function sayHi(){alert('Hello JS')}
}

 
要在flash中調用這個函數,能夠用兩個辦法:

navigateToURL(new URLRequest( 'javascript:sayHi()' ), '_self'); //實際上打開一個新窗口,只不過url是javascript:sayHi(),這是土鱉方法
ExternalInterface.call( 'sayHi');// 用到了ExternalInterface類,這種方法也是adobe推薦的作法

 
運行結果,發現兩個都無法執行,這是由於flashplayer只能看到頁面上全局的javascript,因此要想能讓flash拿到這個js函數,必須暴露出來。修改代碼在運行

window.onload=function (){
     function sayHi(){alert('Hello JS')}
     window['sayHi'] = sayHi;
}

 
代碼成功運行了,因而,咱們能夠總結出一點:提供給flash調用的js函數必須是全局的,獲取寄宿在全局對象上的。

     有時候咱們只用到了flash的功能,而沒用到它的UI因此想把flash隱藏,好比作一個即時通信的東西,只有通信部分用到了flash, 當嘗試把flash設置成display:none的時候,發現js與as根本沒法相互調用,因此說若是須要隱藏flash,設置css是行不通的,能夠 設置它的寬高爲1px來解決。

     若是是想在js中調用as方法,須要用ExternalInterface.addCallback註冊as方法,讓他暴露在flash實例上。好比flash中有這樣的方法:
private function sayHi():void{
     Alert.show('Hi As');
}
External.addCallback('jsSayHi', sayHi);
 
這樣就能夠在js中執行jsSayHi這個代理方法,它會去執行sayHi這個as方法。jsSayHi這個代理方法會寄宿在flash dom元素上,做爲dom元素的方法。
window.onload=function (){
     document.getElementById('flashId').sayHi();
}
 
測試一下,仍是發現了問題,有時候能正常運行,但有時候會拋出錯誤:Uncaught TypeError: Object #<HTMLObjectElement> has no method 'jsSayHi',這是由於即便當前頁面onload了,可是flash中的代碼初始化還沒運行完,因此尚未把代理方法註冊到flash dom元素上。(查看實例3-jscallas_b.html)

     那麼,flash有沒有相似domready的時間點呢?查看好多資料沒看到,可是能夠模擬一個。咱們認識當flash能正常調用頁面上的js時,flash能正常跟js進行交互。咱們在頁面上定義一個flashready函數,讓flash回調。
function flashready(){
     document.getElementById('flashId').jsSayHi(); 
     alert('flash is ready');    
}
 

ExternalInterface.call( 'flashready' );
 

     這樣js對as的調用就能100%的成功了。

     對於靜態資源每每會放在cdn上,好比有一臺cdn域名是cdn.com,而主域名確是xxx.com,這樣就出現了跨域的問題。瀏覽器的安全策略致使 ajax不能正常的跨域請求,flash player的安全策略一樣不容許flash跨域請求和調用。當遇到跨域時,flash player會拋出「安全沙箱衝突錯誤」。其實flash是支持跨域的,只不過要作一些設置。

     若是是跨域腳本執行,flash中有Secure.allowDomain(somedomain1, somedomain2)來容許制定的url請求,somedomain也能夠是通配符"*",也就是不作源限制。若是flash的url是https的 連接,則須要用allowInsecureDomain()來作沙箱橋,但若是當前html也是https,那不須要用它。儘可能避免使用 allowInsecureDomain會削弱https的安全性。可是在一些國產瀏覽器中,好比騰訊TT,遨遊,360等瀏覽器中,常常會遇到第一次進 來js能正常調用flash中的as,可是當刷新一次頁面,發現調用不成功了。這是由於第二次訪問的時候,flash被緩存到了本地,這些瀏覽器破壞了 flash和瀏覽器的某種約定,因此致使他們不能相互調用。
     這個問題有兩個作法:1、當flash文件很小時,用無緩存的方式解決,好比請求後面加隨機數。2、延遲Flash的初始化功能。經過將Flash的 ExternalInterface.addCallback初始化時間延後一些(好比500ms),就能夠解決這個問題。
     順便提一下,若是是flash中的http/socket等跨域請求,則須要一個叫crossdomain.xml的策略文件。這個文件放在服務器上,若是是跨域請求,在請求真實地址以前會去請求這個安全策略文件。
<cross-domain-policy>
<allow-access-from domain=」*.xxx.com」/>
<allow-access-from domain=」*.xxx.net」/>
<allow-access-from domain=」*.xxxcdn.com」/>
<allow-access-from domain=」*.allyes.org」/>
</cross-domain-policy>
 

     有人可能會考慮js與as之間頻繁的相互調用會帶來性能問題。簡單的作了下測試
測試代碼以下:
 
function flashready(){
       var swf = document.getElementById('performance'), //方案1
       //var swf = {'test':function(){return 1}}, //方案2
			test = swf.test,               
			i = 10000;    
							
	   var start = + new Date;
	   while(i--){
			test.call(swf);
	   }
	   alert(+ new Date - start);                 
}
 
flashready是一個全局的,提供給flash初始完回調的函數。注意代碼中把獲取flash dom放到一個變量裏,由於dom操做自己開銷大,若是不這麼作會影響精確性。實驗結果以下:
測試項目(測10次取平均值) chrome 19 firefox 9 ie6 ie7 ie8 ie9
js調用as 10000次耗時(方案1) 1747ms 1083ms 360ms 557ms 485ms 401ms
js調用js 10000次耗時(方案2) 1ms 4ms 15ms 31ms 15ms 0ms
 
觀察結果,雖說js與as執行的執行要比js與js之間慢不少不少,可是勉強仍是能接受的,即便是最慢的chrome,平均調用一次也只須要0.17ms,但仍是要儘可能減小相互調用的次數,就像減小http請求同樣。
 
綜上所述,js與as的安全交互必須知足:
  1. <param name='allowScriptAccess' value ='always' />   
  2. flash不能隱藏(display:none)  
  3. 等被調用方初始化完成再去調用,as中能夠用ExtercalInterface.call('flashready')來告知初始化完成
  4. 跨域執行,必須在flash中設置Secure.allowDomain或者Secure.allowInsecureDomain
相關文章
相關標籤/搜索