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
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 的測試結論
- 使用 opaque/transparent 模式,只需 div 就可以遮擋住 Flash;
- 使用 window/direct/gpu 模式:
- IE 需要藉助 iframe 才能遮擋 Flash
- Chrome 僅 div 即可遮擋 Flash
- Firefox 當使用 rgba 的半透明背景色浮層時,無法遮擋 Flash
- Windows Safari 即使 iframe 也無法遮擋 Flash
- 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 ,隱藏一個層通常有三種方式:
visibility:hidden;
display:none;
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:
- wmode 的五種取值下 Flash 隱藏再顯示的均表現一致;
- IE gpu 模式,
visibility:hidden
的隱藏模式,會使視訊回放1秒;
隱藏視訊的結論:
visibility:hidden
和left:-1000px
的方式,IE6-10、Firefox、Chrome、Safari 瀏覽器中 Flash 的隱藏與顯示都不影響其正常播放(若想隱藏 Flash 時暫停視訊的播放,可以呼叫 Flash 相應的 js 方法實現);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
即可。
<video>
元素無論 Windows、Mac、iOS 還是 Android,普通的 div 元素都能輕鬆遮擋
轉載自:http://note.rpsh.net/posts/93717-div-flash