随着浏览器的图形渲染能力不断提高,设计的能力也变的越来越真实。几行代码就能产生快速且富有视觉冲击力的效果。和大多数web开发一样,有很多种方法来实现同样的效果。
在这篇文章中,我们将会评估最流行的”图片特效”,”灰度(grayscale)”在HTML canvas,SVG,CSS滤镜,和CSS混合模式下的难易程度。
滤镜的作用就像在图片上附加了一个镜头,在被应用到浏览器后,浏览器才开始布局和渲染,在所支持的浏览器上,滤镜能被单独应用或叠加在其他过滤器的顶部。因为它们可以被用作图像修改后的初始渲染,并有可能是一个增强,滤镜优雅地降低,在不支持滤镜的浏览器上,滤镜可以优雅的降级,即不显示滤镜效果。
CSS滤镜
让我们开始用最简单的方法产生灰度效果:不起眼,但很强大的CSS滤镜。
为了达到这个效果,我们添加一行CSS: filter: grayscale(1)
。这个滤镜可以使用与0和1(或0%至100%)之间的任何数字或基于百分比的值来降低图像的饱和度。注:目前,基于WebKit的浏览器滤镜必须添加-webkit-
前缀。
CSS滤镜Demo
.cssfilter-gray { -webkit-filter: grayscale(1); background: url('img/bird.jpg'); filter: grayscale(1); }
背景混合模式
CSS混合模式提供N多种图像效果的组合选择。有两种方式使用混合模式:混合混合模式属性和背景混合模式属性。
mix-blend-mode
:让元素内容和这个元素的背景以及下面的元素发生“混合”。background-blend-mode
:可以是背景图片间的混合,也可以是背景图片和背景色的混合。
在例子中,我们可以使用background-blend-mode: luminosity 来拉光度通道,从而产生成一个灰度图像。
有一点要注意的是,为了让背景保持固定:为了让效果正常显示,背景图像总是必须纯色或渐变背景,颜色必须是最后一个背景层。这也是对不支持background-blend-mode
浏览器的一种保护,也就是说在老的浏览器中不会有混合效果。
混合模式和CSS滤清唯一的不同点是:我们有多个背景,并正使用background-blend-mode: luminosity
,它抓住了图像顶部的亮度值和在灰色的第二个背景层的亮度值。
背景混合模式Demo
.cssfilter-gray { background: url('img/bird.jpg'), gray; background-blend-mode: luminosity; }
目前,这是最新并且最少支持的选项,虽然在 Chrome 和 firefox 浏览器有效,而且在Safari 有部分支持。注意:Safari 支持所有的混合模式除了基于HSL的混合模式:色相、饱和度、颜色和亮度。
HTML5 Canvas
当HTML5 <canvas>
来到的图像操作时,有非常多的灵活性,因为我们有权访问每个单个像素数据 (特别是通过 canvasContext.getImageData),通过 JavaScript可以操作任意一个。但是,这种方法是最复杂的和带有最开销。它也有出于安全考虑,跨域问题的一些细微差别。
要修复Chrome中的跨域错误,你的图像需要一个友好的、跨资源共享的网站,例如可以托管在GitHub或者Dropbox,并指定crossOrigin="Anonymous"
。请看Demo
实现 <canvas>
灰度效果的途径是要清除任何非红色、 绿色和蓝色成分中的像素值,同时维持其亮度水平 (亮度)。一种方法是取 RGB 的平均值 ︰ 灰度 = (红 + 绿 + 蓝) / 3;
。
在下面的示例中,我们使用 RGBa 值的格式 (R、 G、 B) 中的图像数据;红色通道数据 [0],绿色通道是数据 [1],等等。获取每一种渠道 (亮度) 的亮度级别,然后他们取平均值转化为灰度。
HTML5 Canvas Demo
SVG滤镜
SVG滤镜有最广泛的支持(甚至在 Internet Explorer 和Edge! !),和 CSS 滤镜一样,也是容易使用。您可以使用它们具有相同的滤镜属性。事实上,CSS滤镜来源于SVG滤镜。如同画布,SVG滤镜可以让你超越二维效应的平面,因为你可以利用WebGL的阴影来创建更复杂的结果。
与SVG过滤器最大的不同是,我们需要小心包括和链接到该滤镜的正确路径。这意味着我们需要在页面上导入我们正在使用的SVG(通过使用模板引擎,包括语句会更加简单创建出来)。
SVG滤镜Demo
<svg> <filter id="grayscale-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>
渲染图像的速度总是比其他方法慢。
为了公平起见,我想也比较多个图像的加载时间。我为每种方式创建了10个图片,并再次运行该测试(下面视频需翻墙)︰
在这种情况下,CSS滤镜慢了0.1毫秒,表明在CSS滤镜,混合模式和SVG滤镜中,结果最快的方法是不确定的。
更深层次的考虑到页面加载时间通过 JavaScript 渲染和绘制渲染时间,你可以看到这个趋势会持续下去。
Filter Type | Time to Render | Time to Paint |
---|---|---|
CSS Filter | 12.94ms | 4.28ms |
CSS Blend Mode | 12.10ms | 4.45ms |
SVG Filter | 14.77ms | 5.80ms |
Canvas Filter | 15.23ms | 10.73ms |
再一次的,<canvas>
又花了最长的时间去渲染,两个CSS选项都是都是最快的,SVG则在中间。
这些结果有意义,因为<canvas>
是以每个单独的像素,对执行操作它之前我们看不到任何图像。这在渲染时需要大量的处理能力。虽然通常用 Svg 的矢量图形,我将仍然强烈建议他们在 <canvas>
时处理光栅图像效果。不仅速度更快,是 SVG,这也是更容易处理和DOM 更灵活一般,CSS 滤镜更优化比 SVG 滤镜,因为从历史上看,它们是产生 SVG 滤镜的快捷方式,因此,在浏览器中进行了优化。
不用滤镜
不用滤镜会怎么样呢?我在上传之前用照片编辑软件编辑图像(我用预览Mac OS X上删除饱和度),用这种方式来跟速度最快的方法(添加CSS滤镜)比较。当预编辑图像的时候,我发现性能提升了0.1ms。
总结
图片滤镜是一个有趣和有效的方式在web上提供视觉上的统一和审美。请记住,用滤镜会有一定的性能损耗,但也与提供了在浏览器和设计的交互性。
对于简单的图像可以用CSS滤镜,因为可以被很好的支持,用法也简单。对于复杂的图像,可以查阅SVG滤镜或者CSS混合模式。SVG滤镜效果最好,因为SVG滤镜对路径的控制能力和feColorMatrix。在有重叠元素的情况下,CSS滤镜提供了很好的视觉效果。你可以在SVG内使用混合模式(例如feBlend),尽管在这个意义上它们是类似于CSSbackground-blend-mode
,相互作用且涉及SVG的本身,而不是与周围的元素,如mix-blend-mode
允许的话。只是不要用<canvas>
滤镜。
英文原文:https://www.smashingmagazine.com/2016/05/web-image-effects-performance-showdown/