來寫個有煙霧特效的網頁吧

Chris Chuang
Chris Chuang
Published in
3 min readMay 2, 2019

--

利用 css 結合 <video /> 產生動態煙霧特效

最近在寫 JS地下城 第 14 關, 題目的要求是寫一個線上求籤 (占卜) 的網頁。在看完 UI 設計稿提供的背景圖後,我覺得加個煙霧特效應該還不錯,會有廟宇的香正在燃燒的錯覺。

但是在測試過一些產生煙霧的 JS library 後,總覺得效果都不太自然,或者說需要開發者自己去設計出自然的感覺。後來偶然看到這個教學影片,才發現一個比較簡單的做法: 先找個有煙霧特效的影片,再利用 css 的 opacitymix-blend-mode 屬性讓影片與背景的圖層融合在一起,就可以在背景上產生自然的煙霧特效,效果可以參考最後的 成品

什麼是 mix-blend-mode

mix-blend-mode 是一個比較少見的 css 屬性,它可以讓某個 DOM 元素的圖層與下層 DOM 元素的圖層混合在一起。

舉例來說,我們先在圖片上放一段文字:

如果在文字上加上 css 屬性: mix-blend-mode: exclusion ,就會讓背景的圖層與文字混合:

mix-blend-mode 混合圖層的模式目前有 16 種,詳細的參數與效果可以參考這個網站

將 mix-blend-mode 與 <video /> 整合

有了上面的基礎,就可以開始嘗試與 <video /> 整合了。

首先先寫個 .bg包住影片與背景圖,並且讓影片放在背景圖之下:

出來的結果會長這樣:

因為背景圖完全擋住了影片,所以目前只看到圖片是正常的。

接下來,我們就對背景圖補上 mix-blend-mode 屬性,就可以讓背景圖與底下的影片檔的圖層混合在一起:

接者繼續調整其他細節。在 .bg-video上補上 opacity: 0.7 讓影片的圖層顯示淡一點,然後設定 <video /> 屬性讓影片可以自動播放並無限循環:

修改的效果就會長這樣:

<video /> 的解析度問題

到目前為止都跟預想的差不多,唯一的問題就是無論怎麼調整 <video /> 的大小,影像都會維持原始解析度的長寬比。因此如果背景的長寬比與影像的長寬比不同,就會有部分位置沒有煙霧特效。

一個簡單的解決方法,就是故意拉大影像再用外層容器的 css 屬性 overflow: hidden 把超出的部分隱藏起來:

為了方便說明,上面的範例還沒加上 overflow: hidden 。這個做法還可以再優化,比如說把影像調整到置中位置、每當視窗 resize 的時候都重新比較 <video /> 與背景的長寬比再決定要拉大影像的哪個維度。

如果不能接受部分影像被裁切,另一種做法是把影像繪製到 <canvas />上,再把 <canvas /> 延展到與背景相同大小。修改 html 如下:

然後修改 css 把 <video /> 隱藏起來,並且把 canvas 放到圖片下方:

最後再加上繪製影片到 canvas 的程式碼:

這樣就完成了 🎉

結語

最後在結束前再聊一下瀏覽器兼容的問題吧。

mix-blend-mode 在 IE 或 Edge 上都不支援,如果需要兼容這些瀏覽器可以考慮只用 opacity 來疊加影片與背景圖片,當然這樣可以玩的特效就會少很多。

另外部分瀏覽器並不允許載入網頁後自動播放影片,如果一樣需要兼容….那這篇介紹的方法可能就不太適合 😅。

以上,如果有任何問題都歡迎討論喔~

--

--