天天看點

轉載:js和as間的互動

轉載一:

提及AS3與外部腳本的互動,筆者認為可以總結成兩種。一是AS3調用外部函數,二是外部腳本調用AS3函數。無外乎就 這兩種。在調用函數的同時,我們還可以向函數傳遞一些參數。這就達到了傳遞資料的目的。舉一個最簡單的例子。我們平時在網絡上看視訊的時候,這些用AS3 制作的播放器就是由外部腳本(可能是JS,也可能是ASP或其他腳本)傳遞給它的視訊位址。進而就簡化我們的背景程式。有的人會問!你用播放器去讀取外部 的XML資料不是也可以嗎?确實,當時,當你有成千上萬個視訊的時候,你不可能輸入這麼多資料。一是比較麻煩,二來是影響了網頁運作的速度。是以,AS3 與外部腳本進行互動是非常重要的。

      其 實,我們做的絕大多數帶有互動性的FLASH程式都要多多少少與背景的其他語言進行互動。這裡,我們就以JS腳本來舉例說明互動的過程。當然,AS3與 JS腳本可以說有血緣關系,具體的大家可以去檢視一下FLASH的發展曆史。好了!廢話不多說,我們這就開始講如何讓JS與AS3進行一些資訊的交換。本 節中,我們隻講解JS調用AS3中的函數。反向的調用我們将在下一節中進行講解!

       首先,我們建立一個FLASH文檔,然後在舞台上繪制一個動态文本,該文本的執行個體名稱為wen_txt。好了!美工的部分就算完成了(我們這裡是一個非常簡單的執行個體,不要求太複雜。力求突出重點)!

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

ExternalInterface.addCallback("abcd",yun);

function yun(zi:String):void{

wen_txt.text = zi;

}

       我

們看,建立一個可以被外部調用的函數實際上就是使用了

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也擁有這樣的權限。那麼好了!我們來看看在網頁中具體是怎樣做的。

        我們這次先來寫網頁代碼,因為網頁這邊是接受端。代碼如下:

     function sendToJavaScript(value) {

         document.forms["form1"].output.value += "\n" + "ActionScript says: " + value;

<body>

     <form name="form1" onsubmit="return false;">

         <textarea cols="60" rows="20" name="output" readonly="true">Initializing...</textarea>

     </form>

       具

體的什麼意思筆者在這裡就不多說了,屬于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);

<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);

 }

    看,這就完成了用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>

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

 function asFunction(varText) {

       document.form2.accept.value= varText;

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有兩個提供互相調用的靜态方法:

Example 1:

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

要在flash中調用這個函數,可以用兩個辦法:

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

代碼成功運作了,于是,我們可以總結出一點:提供給flash調用的js函數必須是全局的,擷取寄宿在全局對象上的。

 有時候我們隻用到了flash的功能,而沒用到它的UI是以想把flash隐藏,比如做一個即時通訊的東西,隻有通訊部分用到了flash,

當嘗試把flash設定成display:none的時候,發現js與as根本無法互相調用,是以說如果需要隐藏flash,設定css是行不通的,可以

設定它的寬高為1px來解決。

     如果是想在js中調用as方法,需要用ExternalInterface.addCallback注冊as方法,讓他暴露在flash執行個體上。比如flash中有這樣的方法:

這樣就可以在js中執行jsSayHi這個代理方法,它會去執行sayHi這個as方法。jsSayHi這個代理方法會寄宿在flash dom元素上,作為dom元素的方法。

測試一下,還是發現了問題,有時候能正常運作,但有時候會抛出錯誤:Uncaught TypeError: Object

#<HTMLObjectElement> has no method

'jsSayHi',這是因為即使目前頁面onload了,但是flash中的代碼初始化還沒運作完,是以還沒有把代理方法注冊到flash

dom元素上。(檢視執行個體3-jscallas_b.html)

     那麼,flash有沒有類似domready的時間點呢?檢視好多資料沒看到,但是可以模拟一個。我們認識當flash能正常調用頁面上的js時,flash能正常跟js進行互動。我們在頁面上定義一個flashready函數,讓flash回調。

     這樣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和浏覽器的某種約定,是以導緻他們不能互相調用。

這個問題有兩個做法:一、當flash檔案很小時,用無緩存的方式解決,比如請求後面加随機數。二、延遲Flash的初始化功能。通過将Flash的

ExternalInterface.addCallback初始化時間延後一些(比如500ms),就可以解決這個問題。

     順便提一下,如果是flash中的http/socket等跨域請求,則需要一個叫crossdomain.xml的政策檔案。這個檔案放在伺服器上,如果是跨域請求,在請求真實位址之前會去請求這個安全政策檔案。

     有人可能會考慮js與as之間頻繁的互相調用會帶來性能問題。簡單的做了下測試

測試代碼如下:

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

0ms

觀察結果,雖然說js與as執行的執行要比js與js之間慢很多很多,但是勉強還是能接受的,即使是最慢的chrome,平均調用一次也隻需要0.17ms,但還是要盡量減少互相調用的次數,就像減少http請求一樣。

綜上所述,js與as的安全互動必須滿足:

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

flash不能隐藏(display:none)  

等被調用方初始化完成再去調用,as中可以用ExtercalInterface.call('flashready')來告知初始化完成

跨域執行,必須在flash中設定Secure.allowDomain或者Secure.allowInsecureDomain

繼續閱讀