网络图像效果性能对决
已发表: 2022-03-10随着浏览器不断提高其图形渲染能力,在其中进行真正设计的能力越来越成为现实。 几行代码现在可以产生快速而引人注目的视觉效果,并且无需太多努力即可实现一致性。 与 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>
用于过滤器。