1. 程式人生 > >div 浮層遮蓋 flash 問題再研究

div 浮層遮蓋 flash 問題再研究

div 浮層遮擋 Flash 的研究汗牛充棟,隨便 Google 一下都能找到浩如煙海的資料,最簡單的解決方案就是使用 wmode="opaque" 或者 wmode="transparent",如此的簡單而又一勞永逸。

沒有特殊需求的到這裡就可以止步了,但是 wmode="opaque" 並不適合所有網站,比如視訊網站,視訊網站對 Flash 的表現效能有著極致的追求,讓我們更傾向選擇使用 wmode="window",現在有了更好的 wmode="driect" 模式。而在 window/driect 的模式下,普通的 div 浮層很難完美地實現遮擋 Flash 的需求。

Wmode 的五種取值

首先,我們瞭解一下 wmode 五種不同取值的含義

Window模式

預設情況下的顯示模式,在這種模式下 flash player 有自己的視窗控制代碼,這就意味著 flash 影片是存在於 Windows 中的一個顯示例項,並且是在瀏覽器核心顯示視窗之上的,所以 flash 只是貌似顯示在瀏覽器中,但這也是 flash 最快最有效率的渲染模式。由於他是獨立於瀏覽器的HTML渲染表面,這就導致預設顯示方式下flash總是會遮住位置與他重合的所有 HTML 層。

Opaque模式

這是一種無視窗模式,在這種情況下flash player沒有自己的視窗控制代碼,這就需要瀏覽器需要告訴flash player在瀏覽器的渲染表面繪製的時間和位置。這時flash影片就不會在高於瀏覽器HTML渲染表面而是與其他元素一樣在同一個頁面上,因此你就可以使用 z-index

值來控制 HTML 元素是遮蓋 flash 或者被遮蓋。

Transparent模式

透明模式,在這種模式下 flash player 會將 stage 的背景色 alpha 值降為 0 並且只會繪製 stage 上真實可見的物件,同樣你也可以使用 z-index 來控制 flash 影片的層級值,但是與 Opaque 模式不同的是這樣做會降低 flash 影片的回放效果,而且在 9.0.115 之前的 flash player 版本設定 wmode="opaque""transparent" 會導致全屏模式失效。

Direct模式

直接渲染模式,在該模式下,flash player 可以通過硬體直接對畫面進行合成,並呈現在螢幕上。使用這種模式能夠得到比 window 模式更好的渲染效果,特別是在視訊播放方面,如果頁面的 flash 需要使用了 stagevideo 或者 stage3D,那麼必須使用這種模式。它有比 window 模式更好的渲染,但也有 window 模式下的所有缺點。

GPU模式

在一些網路電視和移動裝置上可以啟用額外的硬體加速,與其他 wmode 值模式相比,顯示序列的畫素保真度無法保證,其他方面跟 direct 模式相似。

各家視訊網站的 wmode 取值

Youku Tudou Tencent Video iQiyi Sohu TV Letv Sina Video Youtube Vimeo Hulu Flickr Video
N/A window/opaque direct window opaque opaque transparent N/A opaque N/A opaque

N/A 表示沒有設定 wmode 值,此時 Flash 預設使用 window 的取值。
土豆在 XP 下的 IE 和 Chrome 使用了 opaque,其他情況下是 window。

有40.9%的視訊網站採用了 window 的模式;還有 40.9% 的選擇使用 opaque。 window 和 opaque 平分秋色,這樣看來 opaque 也應該是一個不錯的選擇。(不知是這些網站的前端偷懶,還是效能上真的OK。這個稍後需要做一個性能測試後再分享相關資料)

div 遮蓋 Flash 的測試結果

接下來我們來測試不同的 div 浮層遮擋不同 wmode 取值的 flash 的效果,下邊是測試結果一覽表:

wmode=window Windows Mac
IE6-IE10 Chrome Firefox Safari Safari Chrome Firefox
div
div + iframe
div(rgba)
div(rgba) + iframe
wmode=direct Windows Mac
IE6-IE10 Chrome Firefox Safari Safari Chrome Firefox
div
div + iframe
div(rgba)
div(rgba) + iframe
wmode=gpu Windows Mac
IE6-IE10 Chrome Firefox Safari Safari Chrome Firefox
div
div + iframe
div(rgba)
div(rgba) + iframe
wmode=opaque Windows Mac
IE6-IE10 Chrome Firefox Safari Safari Chrome Firefox
div
div + iframe
div(rgba)
div(rgba) + iframe
wmode=transparent Windows Mac
IE6-IE10 Chrome Firefox Safari Safari Chrome Firefox
div
div + iframe
div(rgba)
div(rgba) + iframe

注:div(rgba) 指定義浮層背景半透明色的情況,CSS 程式碼: background-color:rgba(255,255,255,0.6)

div 遮蓋 Flash 的測試結論

  1. 使用 opaque/transparent 模式,只需 div 就可以遮擋住 Flash;
  2. 使用 window/direct/gpu 模式:
    1. IE 需要藉助 iframe 才能遮擋 Flash
    2. Chrome 僅 div 即可遮擋 Flash
    3. Firefox 當使用 rgba 的半透明背景色浮層時,無法遮擋 Flash
    4. Windows Safari 即使 iframe 也無法遮擋 Flash
    5. Mac 系統下 wmode 取任何值, div 元素都能輕鬆遮擋 Flash 元素
特例1: Windows 版的 Firefox

只有具有背景色(background-color:#fff)的元素才能遮擋 Flash,透明背景(background:transparent),或者背景顏色為半透明(background-color:rgba(255,255,255,0.5)),或者使用半透明圖片(background:url(alpha.png))做背景的元素都無法遮擋 Flash

特例2: Windows 版的 Safari

上述 2.4 的結論有點讓人沮喪,雖然 Windows 版 Safari 的份額處於異常邊緣的位置,不過遇到這個問題還是解決,我們的解決方案是,當出現需要遮蓋 Falsh 的浮層時候,暫時隱藏 Flash ,隱藏一個層通常有三種方式:

  1. visibility:hidden;
  2. display:none;
  3. positiona:relative;left:-1000px;

這裡我們需要的隱藏應當達到如下效果:視訊暫時不可見,浮層關閉後,Flash 視訊應當繼續播放。

以下是在 Windows 版各個瀏覽器中的測試結果

IE6-IE10 Chrome Firefox Safari
visibility:hidden A A A A
display:none A B B B
left:-1000px A A A A

注1:

  • A: 視訊隱藏,繼續後臺播放,切換回來後可繼續正常播放
  • B: 視訊隱藏,停止播放,切換回來後從頭重新開始播放

注2: 

  1. wmode 的五種取值下 Flash 隱藏再顯示的均表現一致;
  2. IE gpu 模式,visibility:hidden 的隱藏模式,會使視訊回放1秒;
隱藏視訊的結論:
  1. visibility:hiddenleft:-1000px 的方式,IE6-10、Firefox、Chrome、Safari 瀏覽器中 Flash 的隱藏與顯示都不影響其正常播放(若想隱藏 Flash 時暫停視訊的播放,可以呼叫 Flash 相應的 js 方法實現);
  2. display:none ,會導致視訊在 Chrome、Firefox、Safari 中視訊重新載入,從頭開始播放;

這裡建議使用 visibility:hidden 的方法來隱藏視訊,相容性和對頁面重繪的影響都最小。

div 遮擋 HTML5 視訊研究

說完 Flash 了,我們順道研究一下 div 浮層遮擋 HTML5 Video 是否會有問題。經測試,結果如下表:

HTML5 Video Windows Mac iOS Android
IE9-IE10 Chrome Firefox Safari Chrome Firefox Safari Chrome 原生 Chrome UC
div
div + iframe
div(rgba)
div(rgba) + iframe

注: iPhone 上當視訊播放時會自動切換為全屏,此時沒有任何頁面元素可以遮擋它。當視訊處於非全屏的暫停(或未開始播放)狀態時, div 浮層可以遮擋 <video> 元素。iPad 上無此問題。

HTML5 Video 的得天獨厚的優勢 —— 無外掛的視訊播放,使其跟頁面其他元素處於一種平等的層級關係上,div 浮層輕輕鬆鬆即可實現遮擋 <video> 內容。

div 浮層遮擋 Flash 的最終結論

對於 Flash
Windows 系統下:
如果可以使用 wmode="opaque" 或者 wmode="transparent" , div 浮層遮擋 Flash, 只需設定好 div 浮層的 z-index 即可。

如果必須使用 wmode="window" 或者 wmode="driect" ,相容各個瀏覽器的 div 浮層遮擋 Flash 的方案是使用 div + iframe 方式,而如果實現半透明的浮層效果(包括:背景色使用rgba,背景圖帶有透明的 png、gif 等),則要對 Firefox 進行特殊處理,單獨定義 Firefox 使用純色的背景。

/* Fierfox hack 參考 */
@-moz-document url-prefix(){
    .div_layer { 
        background-color: #fff;
        border-radius: 0; /* 遮擋Flash的浮層若設定圓角,在 Firefox 上會出現缺角的bug,需重置為0 */
    }
}

若還需要相容 Windows 版的 Safari,則需要在遮擋 Flash 的浮層出現時,隱藏掉 Flash,隱藏 Flash 的方法推薦使用 visibility:hidden

Mac 系統下:
無需擔心 div 浮層的遮擋關係, 只需設定好 z-index 即可。

對於 HTML5 <video> 元素
無論 Windows、Mac、iOS 還是 Android,普通的 div 元素都能輕鬆遮擋

轉載自:http://note.rpsh.net/posts/93717-div-flash