1. 程式人生 > >flash插入頁面後在IE下stageWidth為0的bug

flash插入頁面後在IE下stageWidth為0的bug

用SWFObject,將swf檔案嵌入網頁後,在IE瀏覽器中首次瀏覽正常,重新整理後,stageWidth就為0了,swf中基於stageWidth定位的元素,就會錯亂。

轉自(ljhzzyx 2009-09-24 14:44:20

首先區分一下stage的stageWidth和width屬性。stage.stageWidth是flash player的寬度,stage.width是指stage裡content的寬度,如果這個舞臺(stage)裡什麼內容都沒有,stage.width就是0。

        現在的需求是在執行期獲得舞臺的高寬,以期編碼實現將元件新增到舞臺中央等這樣的效果。但是我得到的stageWidth 和 stageHeight 都為0。

Turns out that when the stage is initialized, it's stageWidth and stageHeight properties are 0 until a Stage RESIZE event is triggered. This event is dispatched when the scaleMode property of the Stage object is set to StageScaleMode.NO_SCALE and the SWF file is resized ie. when the stage is rendered by the Flash Player. So if you need to add a display object onto the stage and its positioning is dependent on the stageWidth or stageHeight properties at runtime, it’s best handled by a listener that is subscribed to the Stage RESIZE event.
       在IE中SWF檔案的stageWidth 和 stageHeight 被初始化為0,再延遲一段時間後會更新成正確的數值。在SWF檔案更新stageWidth 和 stageHeight屬性時,會觸發stage物件的resize事件。因此, 可以給stage新增resize事件處理器,將取得stageWidth 和 stageHeight值及後續工作放在resize處理函式裡做,一旦stageWidth 和 stageHeight值大於0,則將此resize監聽器取消掉。

Interestingly, despite universal claim that the Flash Player behaves exactly the same on all browsers, this problem only appears in a couple of browser/plugin configurations, namely FireFox/OSX and IE/Win. And strangely, on Safari and Firefox/Win, the RESIZE event is not even dispatched on page load, and neither does the Flash Player register the stageWidth and stageHeight properties as being 0. I have not tested the problem on other platforms but you are certainly welcome to do so yourselves and report your observations in the comments section. 
       一般認為,flash檔案在不同瀏覽器中的行為是一致的。如上所述,在FireFox/OSX 和 IE/Win這種搭配才有這樣的bug。

SWFObject.js裡的解決方案

在swfobject.js裡找到函式function createSWF(attObj, parObj, id)裡面針對winIE的處理方法是:
        el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
       看了一下Adobe自己的AC_OETags.js,他是用document.write方法直接寫入,沒有這個問題;
       直接寫靜態html(object)沒有這種問題;
       直接訪問這個flash的地址,也沒有這種問題。

SWFObject在IE下的BUG
如果Flash裡繪製的物件的寬高是自適應Flash的寬高的,那麼,使用SWFObject來插入Flash在IE會導致一個問題,當這個Flash被快取後,也就是第二次訪問該頁面時,在該Swf檔案被載入時,獲取到的stage.stageWidth和stage.stageHeight為0,繪製的物件也就看不到了。


在Flash裡監聽resize事件,找出解決方法
用IE的話,會看到5行,有兩次resize事件,這也就導致了Flash在載入的時候繪製物件錯誤(寬和高為0):
數字是stage.stageWidth和stage.stageHeight

info
resize
0 x 0
resize
300 x 300

如果用Firefox等瀏覽器,只輸出兩行文字,沒有resize事件:

info
300 x 300

AS裡的解決方案
通過監聽resize事件,當stage.stageWidth和stage.stageHeight大於0時再進行初始化
package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.text.TextField;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;

    public class AutoSizeExample extends Sprite
    {
        private var txt:TextField;
        public function AutoSizeExample()
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            txt = new TextField();
            txt.multiline = true;
            txt.wordWrap = true;
            txt.text = "info/n";
            addChild(txt);

            if (stage.stageWidth>0 && stage.stageHeight>0){
                createChild();
            }else{
                stage.addEventListener(Event.RESIZE,onResize);
            }
        }

        private function onResize(e:Event):void
        {
            if (stage.stageWidth>0 && stage.stageHeight>0){
                stage.removeEventListener(Event.RESIZE,onResize); //刪除事件監聽
                createChild();
            }
            //否則繼續監聽事件,直到stage.stageWidth和stage.stageHeight大於0時才初始化
        }

        private function createChild():void
        {
            //進行初始化操作,建立各物件
            //.......................
            var w:Number = stage.stageWidth;
            var h:Number = stage.stageHeight;

            txt.appendText(w + " x " + h + "/n");
        }

    }
}