as和js通信最早用的是fscommand,這個我就不說了,老生常談了,我們這里說的是ExternalInterface這個接口。大家都知道的或者一幫在網(wǎng)上能查到的東西我就不費吐沫了,撿最實在的說。ExternalInterface有兩個方法,一個是call,是as調(diào)用js,這個沒什么說的,我們現(xiàn)在主要說addcallback這個函數(shù),這個函數(shù)是as注冊一個函數(shù),然后讓js通過調(diào)用flash這個object對象來調(diào)用as注冊的這個函數(shù)。注意,我這里說的是“js調(diào)用flash這個object對象來調(diào)用as注冊的這個函數(shù)”,這里我強調(diào)了先調(diào)用object對象,然后再調(diào)用函數(shù),為什么要這么強調(diào)呢,因為大家在開發(fā)過程中會遇到兩個坎,一個是調(diào)用flash對象調(diào)用不到,一個是調(diào)用函數(shù)調(diào)用不到了。下面我們就針對這兩種情況進行詳細說明。
有很多朋友在開發(fā)過程中會遇到過下面這些情況,在開發(fā)一個js函數(shù)上來就調(diào)用as的一個函數(shù)的時候,頁面會報錯,提示找不到這個flash對象,或者函數(shù)沒有定義。Flash8的時代,針對ExternalInterface這個類,文檔里只說明了怎么用,而沒有具體說怎么合理的組織和頁面的結(jié)構(gòu),一直到了cs3的時代,幫助里才說明了正確的函數(shù)注冊和js調(diào)用的過程,具體的見Flash cs3幫助。大概的代碼如下:
js部分:
<script>
var jsReady=false;
var swfReady=false;
function isReady(){
return jsReady;
}
function setSwfIsReady(){
swfReady=true;
getSWF(”flashobj”).fun()
}
function pageInit(){
jsReady=true;
}
function getSWF(movieName) {
if (navigator.appName.indexOf(”Microsoft”) != -1) {
return window[movieName+”_ob”];
} else {
return document[movieName+”_em”];
}
}
onload=function(){
pageInit();
}
</script>
注意,在getSWF函數(shù)里我用了 return window[movieName+”_ob”]和return document[movieName+”_em”],為什么這樣用我會在下面說明,一幫的情況下只需要用movieName就可以了
as部分
private function registerJsFun():void{
if(ExternalInterface.available){
try{
var containerReady:Boolean=isContainerReady();
//ExternalInterface.call(”ceshi”,”registerJsFun:”+containerReady);
if(containerReady){
//注冊函數(shù)
setupCallBacks();
}else{
//檢測是否準備好
var readyTimer:Timer=new Timer(100);
readyTimer.addEventListener(TimerEvent.TIMER,timeHandler);
readyTimer.start();
}
}catch(error:Error){
trace(error)
}
}else{
trace(”External interface is not available for this container.”);
}
}
private function timeHandler(event:TimerEvent):void{
var isReady:Boolean=isContainerReady();
if(isReady){
Timer(event.target).stop();
setupCallBacks();
}
}
private function isContainerReady():Boolean{
var result:Boolean=Boolean(ExternalInterface.call(”isReady”));
return result;
}
private function setupCallBacks():void{
ExternalInterface.addCallback(”fun”,fun);
ExternalInterface.call(”setSwfIsReady”);
}
具體我就不解釋了,不明白的同學可以仔細去看下cs3幫助,大概的意思就是頁面開始渲染的時候js去調(diào)用swf對象,有可能swf對象沒有完全load完,所以這個觸發(fā)器要從flash開始,當flash加載的時候就開始不停的調(diào)用頁面的一個函數(shù),取一個頁面是否加載完畢的標識,當pageonLoad后,這個標識為true了,說明flash也加載完畢了,這個時候flash再開始注冊函數(shù),同時調(diào)用頁面的js,讓js調(diào)用Flash對象,感覺繞了一大圈,但這是官方推薦的方法。在flash8的時候,我不知道這么用,采用了一種比較笨的辦法,就是setTimeout執(zhí)行addCallback來注冊as函數(shù),大家可能要問為什么這么麻煩。我再后面會說明。
好了,現(xiàn)在我舉兩個最實際的例子,在我開發(fā)搜狗音樂盒的時候,因為播放音樂的工作完全交給mediaPlayer這個微軟的Object。然后又要在flash里實時的顯示歌曲的進度,音量等信息,不得不頻繁的在as和js之間不停的調(diào)用,那段時間簡直痛不欲生。而且mediaPlayer這個對象還有好多版本的內(nèi)核,從6.4到11,當時我了解了不少這方面的信息,如果有同學對這個感興趣,可以寫mail給我。扯遠了,繼續(xù)說我們這個問題,當時產(chǎn)品上線的時候,在我本機的resin上測試,沒有任何的問題,但是一上真實的生產(chǎn)環(huán)境,就出問題了,什么問題呢,IE和ff下是沒有問題的,問題處在tt(就是騰訊那個瀏覽器)和遨游瀏覽器上,清掉瀏覽器的cache,沒有問題,第2次刷新的時候,產(chǎn)生腳本錯誤,調(diào)用as函數(shù)失效。而在我本機怎么測都沒有問題,后來發(fā)現(xiàn)原來是我本機沒有設(shè)置resin的cache,既沒有過期頭。為什么一有cache as注冊的函數(shù)就失效呢,這也是為什么cs3的時候出了一套規(guī)范的流程來規(guī)定如何使用addCallback,因為flash一旦在瀏覽器里cache住,如果在as里一開始就addcallback就會失效,至于為什么我到現(xiàn)在也說不清楚,解決的辦法就是用官方的辦法,如上的代碼或者用我當時的笨辦法
setTimeOut(registerFun,50)
registerfun就是實現(xiàn)addCallBack的函數(shù),這樣就能避免TT和遨游瀏覽器下如果cache住的時候,addcallback失效的問題。
還有一個辦法我沒有嘗試,就是如果你是 用Flash開發(fā),把displayObject放在第一幀,而addCallback放到第二幀上,為什么這么做呢,這是我從Flex那得到的靈感,在Flex下,這樣寫,在Application里寫
creationComplete=initApp();然后在initApp里addCallback
多說一句,F(xiàn)lex程序是分成兩幀,第一幀是preload,第二幀才開始渲染界面,然后在Application下有三種狀態(tài)preinitialize,initialize,creationComplete,這三個的意思分別就是在初始化前,初始化,和界面完全渲染完畢
那么如果你在界面完全渲染完畢的時候addCallback,才能保證有效。
現(xiàn)在我來解釋為什么之前我用的return window[movieName+”_ob”]和return document[movieName+”_em”],在IE下,如果object標簽和embed表現(xiàn)用同樣的id,通過js去訪問flash對象的時候,IE會認不出,F(xiàn)F是沒有問題的,至于為什么我不知道,所以,我當初在搜狐做視頻播放器的時候采用這樣的方式
<object id=”player_ob” name=”player” classid=”clsid:d27cdb6e-ae6d-11cf-96b8-444553540000″ codebase=”http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0” width=”100%” height=”100%” align=”middle”>
<param name=”allowScriptAccess” value=”always” />
<param name=”movie” value=”Main.swf” />
<param name=”quality” value=”high” />
<param name=”allowFullScreen” value=”true” />
<embed id=”player_em” name=”player” src=”Main.swf” mce_src=”Main.swf” quality=”high” bgcolor=”#000000″ width=”100%” height=”100%” align=”middle” allowScriptAccess=”always” allowFullScreen=”true” type=”application/x-shockwave-flash” pluginspage=”http://www.macromedia.com/go/getflashplayer” />
</object>
然后你就知道我前面為什么那么寫了,所以,勸解大家一句,盡量不要用那個swfObejct.js這個東西,as和js交互起來很麻煩。你可以自己寫一個簡單的insertFlash.js
function insertFlash(elm, url, w, h) {
if (!document.getElementById(elm)) return;
var str = ”;
str += ‘<object width=”‘+ w +’” height=”‘+ h +’” id=”demo” classid=”clsid:D27CDB6E-AE6D-11cf-96B8-444553540000″ codebase=”http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0″>’;
str += ‘<param name=”movie” value=”‘+ url +’”>’;
str += ‘<param name=”quality” value=”high”>’;
str += ‘<param name=”wmode” value=”Transparent”>’;
str += ‘<param name=”allowscriptaccess” value=”always”>’;
str += ‘<embed width=”‘+ w +’” height=”‘+ h +’” src=”‘+ url +’” quality=”autohigh” wmode=”opaque” type=”application/x-shockwave-flash” plugspace=”http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash“></embed>’;
str += ‘</object>’;
document.getElementById(elm).innerHTML = str;
}
至于版本的判斷和版本的升級,大家去Adobe官方網(wǎng)站去下檢測包吧。我就不多廢話了,不過上次我用了半天,檢測版本號一直不對,檢測是否安裝倒是可以
好了,先就寫這些了,希望對同學們有所幫助
最近開發(fā)遇到的問題更偏向于js了。寫了一個程序,讓js與flash通訊,結(jié)果flash能調(diào)用js方法,但是js竟然不能調(diào)用flash方法。比如說我在flash中開放了接口“abcd”,但是用js調(diào)用 swf.abcd()。竟然報錯說abcd不是方法。
這個問題是只出現(xiàn)在firefox下,ie下運行正常。于是開始狂使用alert了——后來發(fā)現(xiàn)firebug可以斷點調(diào)試,長嘆!
發(fā)現(xiàn)在firefox下通過document.getElmentById(swfid)能找到一個EmbedObject,可是就是找不到abcd方法。那估計就是在開放接口的時候出現(xiàn)問題了。首先想到的是可能會延遲:有可能在flash object初始化完畢前就執(zhí)行了ExternalInterface.addCallback。這樣自然就找不到方法了。于是使用了個定時器,在2秒后開放接口——2秒的時間估計夠頁面初始化Flash ObjectN個了吧!
發(fā)現(xiàn)還是不行,還是找不到abcd方法。倒~~~~~~ 然后去網(wǎng)上搜,搜到j(luò)s獲取flashobject方法總匯——其實總匯通總會,通過這個方法總會獲取到flashobject的!如下:
window.document[movieName] // (on Mozilla browsers such as Netscape)
window[movieName] // (on Internet Explorer as of ver 5)
document.embeds[movieName] // Mozilla Netscape, Firefox or Opera
===================================================
function getFlashMovieObject(movieName){
if (window.document[movieName]){
return window.document[movieName];
}else if (navigator.appName.indexOf(”Microsoft Internet”)==-1){
if (document.embeds && document.embeds[movieName])
return document.embeds[movieName];
}else{
return document.getElementById(movieName);
}
}
===================================================
很高興啊,趕緊copy!運行~~~~~~~ 靠,竟然還是能找到swf對象,但是找不到abcd方法。吃個飯,細想:估計還是開放接口錯了。繼續(xù)找資料,找到一篇好文章:http://www.akooc.com/article.asp?id=171。竟然也是搜狗的人,還開發(fā)過搜狗音樂盒,好!找到一段話:
如果object標簽和embed表現(xiàn)用同樣的id,通過js去訪問flash對象的時候,IE會認不出,F(xiàn)F是沒有問題的,至于為什么我不知道,所以,我當初在搜狐做視頻播放器的時候采用這樣的方式…………………………….所以,勸解大家一句,盡量不要用那個swfObejct.js這個東西,as和js交互起來很麻煩。你可以自己寫一個簡單的insertFlash.js…………..
暈,估計就是查找flash對象時對錯號了。我也太相信swfobject.js了。動手自己寫標簽,將object和embed的id區(qū)分開來:
//===============================================
//添加pagekit
//===============================================
var url = “PageKit.swf”;
//添加flash變量
var vars = “pagekitInitData=”;
if(this["pagekitInitData"] != undefined) {
vars += this["pagekitInitData"];
}
var ieID = isIE ? pagekitID : pagekitID + “_ie”;
var ffID = isIE ? pagekitID + “_ff” : pagekitID;
var str = “”;
str += ‘<object classid=”clsid:D27CDB6E-AE6D-11cf-96B8-444553540000″ style=”position:absolute”‘;
//str += ‘ id=”‘ + ieID +’” width=”200″ height=”200″‘;
str += ‘ id=”‘ + ieID +’” width=”200″ height=”200″‘;
str += ‘ codebase=”http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab”>’;
str += ‘ <param name=”movie” value=”‘ + url +’” />’;
str += ‘ <param name=”quality” value=”high” />’;
str += ‘ <param name=”wmode” value=”transparent”/>’;
str += ‘ <param name=”allowScriptAccess” value=”always” />’;
str += ‘ <param name=”FlashVars” value=”‘ + vars + ‘” />’;
str += ‘ <embed src=”‘ + url +’” quality=”high”‘;
str += ‘ width=”200″ height=”200″ id=”‘ + ffID +’” align=”middle”‘;
str += ‘ play=”true”‘;
str += ‘ loop=”false”‘;
str += ‘ quality=”high”‘;
str += ‘ wmode=”transparent”‘;
str += ‘ FlashVars=”‘ + vars + ‘”‘;
str += ‘ allowScriptAccess=”always”‘;
str += ‘ type=”application/x-shockwave-flash”‘;
str += ‘ pluginspage=”http://www.adobe.com/go/getflashplayer”>’;
str += ‘ </embed>’;
str += ‘</object>’;
swfDiv.innerHTML = str;
運行!還真對得起這位高人的這篇文章,找到abcd方法了??!艱辛啊~~~~~~
如對本文有疑問,請?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會為你解答!! 點擊進入論壇