網絡圖像效果性能對決

已發表: 2022-03-10
快速總結 ↬隨著瀏覽器不斷提高其圖形渲染能力,真正在其中進行設計的能力越來越成為現實。 幾行代碼現在可以產生快速而引人注目的視覺效果,並且無需太多努力即可實現一致性。 與 Web 開發中的大多數事情一樣,通常有很多方法可以達到相同的效果。 在這篇文章中,我們將看看最流行的圖像效果之一,灰度,並評估 HTML 畫布、SVG、CSS 過濾器和 CSS 混合模式的易於實現和性能影響。 哪一個會贏?

隨著瀏覽器不斷提高其圖形渲染能力,在其中進行真正設計的能力越來越成為現實。 幾行代碼現在可以產生快速而引人注目的視覺效果,並且無需太多努力即可實現一致性。 與 Web 開發中的大多數事情一樣,通常有很多方法可以達到相同的效果。

在這篇文章中,我們將看看最流行的圖像效果之一,灰度,並評估 HTML 畫布、SVG、CSS 過濾器和 CSS 混合模式的易於實現和性能影響。 哪一個會贏?

關於 SmashingMag 的進一步閱讀

  • 網絡圖像效果性能對決
  • HTML5:事實與神話
  • 使用 ImageMagick 高效調整圖像大小
  • 聰明的 JPEG 優化技術

網絡上的過濾器就像放置在圖像上的鏡頭一樣工作。 它們在瀏覽器呈現佈局和初始繪製後應用於圖像。 在支持的瀏覽器中,過濾器可以單獨應用,也可以相互疊加。 因為它們可以在初始渲染後作為圖像修改應用,並且可能是一種增強,過濾器優雅地降級,只是在不支持它們的瀏覽器中不可見。

跳躍後更多! 繼續往下看↓

CSS 過濾器

讓我們從最直接的生成灰度效果的方法開始:不起眼但功能強大的 CSS 過濾器。

未經過濾的鳥圖像
未過濾的圖像。 (查看大圖)

為了達到這個效果,我們添加了一行 CSS: filter: grayscale(1) 。 此濾鏡使圖像去飽和,可用於 0 到 1(或 0% 到 100%)之間的任何數字或基於百分比的值。 注意:目前,基於 WebKit 的瀏覽器的過濾器必須以-webkit-為前綴。 但是,諸如 Autoprefixer 之類的解決方案將消除手動添加它們的需要。

現場演示 - CSS 過濾器

.cssfilter-gray { -webkit-filter: grayscale(1); background: url('img/bird.jpg'); filter: grayscale(1); }

背景混合模式

CSS 混合模式為圖像效果組合提供了無窮無盡的選擇。 有兩種使用混合模式的方法: mix-blend-mode屬性和background-blend-mode屬性。

  • mix-blend-mode是描述元素如何與其後面的內容混合的屬性。
  • background-blend-mode用於具有多個背景的元素,並描述了這些背景之間的關係。

在我們的示例中,我們將使用background-blend-mode: luminosity將亮度通道拉到灰色背景上,從而生成灰度圖像。 需要注意的一點是背景順序是恆定的:背景圖像必須始終在純色或漸變背景之前排序,才能正確渲染效果。 顏色必須是最後一個背景層。 這也是對不支持background-blend-mode的舊瀏覽器的保護——圖像仍然會在沒有效果的情況下呈現。

混合模式和 CSS 過濾器的唯一區別是我們現在有多個背景,並且使用background-blend-mode: luminosity ,它從頂部圖像(鳥類測試儀)中獲取亮度值並將這些亮度值分層灰色的第二個背景。

現場演示 - 背景混合模式

.cssfilter-gray { background: url('img/bird.jpg'), gray; background-blend-mode: luminosity; }

目前,這是最新的,因此受支持最少的選項,儘管它仍然在 Chrome 和 Firefox 中運行良好,並且部分支持 Safari。 注意:Safari 支持除基於 HSL 的混合模式之外的所有混合模式:色調、飽和度、顏色和亮度。

HTML5 畫布

HTML5 <canvas>在圖像處理方面提供了極大的靈活性,因為我們可以訪問每個單獨的像素數據(特別是通過canvasContext.getImageData ),並且可以通過 JavaScript 操作每個像素。 然而,這種方法最複雜,開銷也最大。 由於安全問題,它在跨域問題上也有一些細微差別。

要修復 Chrome 中的跨域錯誤,您的圖像需要託管在 GitHub Pages 或 Dropbox 等跨域資源共享 (CORS) 友好站點上,並指定crossOrigin="Anonymous" 。 請參閱演示的實時示例。

使用<canvas>實現灰度效果的方法是從像素值中的任何離群值中去除紅色、綠色和藍色分量,同時保持其亮度級別(亮度)。 一種方法是對 RGB 值進行平均,如下所示: grayscale = (red + green + blue) / 3; .

在下面的示例中,我們在圖像數據中使用格式為(R,G,B,a)的 RGBa 值; 紅色通道是data[0] ,綠色通道是data[1] ,依此類推。 然後我們得到每個通道的亮度級別(亮度)並將它們平均以轉換圖像灰度。

現場演示 – HTML5 Canvas

SVG 過濾器

SVG 過濾器擁有最廣泛的支持(甚至在 Internet Explorer 和 Edge 中!),並且(幾乎)與直接使用 CSS 過濾器一樣容易。 您可以將它們與相同的filter屬性一起使用。 事實上,CSS 過濾器源於 SVG 過濾器。 與畫布一樣,SVG 過濾器允許您超越二維效果的平面,因為您可以利用 WebGL 著色來創建更複雜的結果。

有幾種方法可以應用 SVG 過濾器,但在這種情況下,我們仍將在背景圖像上使用filter屬性,就像 CSS 過濾器示例一樣以保持一致性。 與 SVG 過濾器的最大區別在於,我們需要小心地使用正確的路徑包含並鏈接到此過濾器。 這意味著我們需要在我們使用它的元素上方的頁面上導入 SVG (這可以通過使用模板引擎和 include 語句變得更容易)。

現場演示 – SVG 過濾器

<svg> <filter> <feColorMatrix type="saturate" values="0"/> </filter> </svg>
 .svgfilter-gray { background: url('img/bird.jpg'); -webkit-filter: url(#grayscale-filter); filter: url(#grayscale-filter); }

過濾器性能

那麼這些在初始渲染性能方面是如何疊加的呢? 我為每個測試頁面製作了一個測試頁面,並使用了 Chrome 47 中的 WebPagetest 比較功能。請記住,每個測試給出的結果略有不同,總體趨勢可以總結如下:

CSS 過濾器、SVG 過濾器和 CSS 混合模式方法都在相對相似的時間範圍內加載。 有時 SVG 過濾器比 CSS 混合模式更快(但總是幾乎沒有),反之亦然。 CSS 過濾器通常是加載速度最快的,而<canvas>總是最慢的。 這是收集到的最重要的見解。 <canvas>在渲染圖像時經常落後於其他方法。

為了公平起見,我還想比較多個圖像的加載時間。 我為每個版本創建了十個(而不僅僅是一個)並再次運行測試:

結果是相似的(請記住,每次測試都有細微的差異)。 在這種情況下,CSS 過濾器慢了 0.1 毫秒,表明在 CSS 過濾器、混合模式和 SVG 過濾器之間,結果對於最快的方法是不確定的。 然而,相比之下,HTML5 <canvas>明顯落後。

通過 JavaScript 渲染和繪製渲染時間深入了解頁面加載時間,您可以看到這種趨勢仍在繼續。

(查看大圖)
過濾器類型渲染時間繪畫時間
CSS 過濾器12.94 毫秒4.28ms
CSS 混合模式12.10ms 4.45ms
SVG 過濾器14.77 毫秒5.80毫秒
畫布過濾器15.23 毫秒10.73 毫秒

同樣, <canvas>花費了最長的渲染時間和最長的繪製時間,而兩個 CSS 選項是最快的,SVG 排在中間。

這些結果是有道理的,因為<canvas>在我們能夠看到任何圖像之前獲取每個單獨的像素並對其執行操作。 這在渲染時需要大量的處理能力。 雖然通常 SVG 用於矢量圖形,但在處理光柵圖像效果時,我仍然強烈推薦它們而不是<canvas> 。 SVG 不僅速度更快,而且在 DOM 中更容易處理和更靈活。 一般來說,CSS 過濾器比 SVG 過濾器更優化,因為從歷史上看,它們是 SVG 過濾器的快捷方式,因此在瀏覽器中進行了優化。

#沒有過濾器

不使用過濾器會怎樣? 我將我們整體最快的方法(添加 CSS 過濾器)與在上傳之前在照片編輯軟件中編輯圖像進行了比較(我在 Mac OS X 上使用預覽來消除飽和度)。 在預編輯圖像時,我在測試中發現了一致的 0.1ms 性能改進:

結論

圖像過濾器是一種有趣且有效的方式,可在 Web 上提供視覺統一和美學吸引力。 請記住,它們確實會帶來輕微的性能影響,但也具有在瀏覽器中快速設計的好處以及設計交互的機會。

對於簡單的圖像效果,請使用 CSS 過濾器,因為它們具有最廣泛的支持和最簡單的用法。 如需更複雜的圖像效果,請查看 SVG 濾鏡或 CSS 混合模式。 SVG 濾鏡效果特別好,因為它們具有通道操作功能和feColorMatrix 。 CSS 混合模式還提供了一些非常好的視覺效果,頁面上的元素重疊。 您可以在 SVG 中使用類似的混合模式(例如feBlend ),儘管它們類似於 CSS background-blend-mode ,因為交互與 SVG 本身相關,而不是與周圍元素相關,如mix-blend-mode允許的那樣。 只是不要將<canvas>用於過濾器。