轉載一:
提及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