SVG 可以实现任何效果,对吧?
与一些优秀的设计师合作一年并进行实验以实现一些很酷的视觉效果后,这种感觉越来越强烈。 在 CodePen 上快速搜索“SVG” 可以证明这一点。从字母、形状、精灵、动画到图像处理,所有内容在 SVG 的帮助下都变得更好。因此,当去年一种新的视觉趋势席卷网络时,SVG 能够帮助我们实现它也就不足为奇了。
趋势的火花
世界各地的创意人士都以 Spotify 在 2015 年的音乐年度网站 (这里是去年的) 中流行起来的色彩化技术为契机,迎来了 2016 年的新年,该网站为其品牌标识引入了大胆的双色调图像。

该技术是一种通过将一种颜色(传统上为黑色)与另一种颜色叠加来实现图像的半色调再现的方法。换句话说,较深的色调将映射到图像的阴影,而较浅的色调将映射到高光。
我们可以在 Photoshop 中通过在图像上应用两种颜色的渐变映射(图层 > 新调整图层 > 渐变映射
)来实现双色调技术。


右键单击(或 alt + 单击
)调整图层并创建剪切蒙版,将渐变映射应用于直接位于其下方的图像图层,而不是应用于所有图层。
以前需要对 <canvas>
元素进行微调,才能计算颜色映射并将结果绘制到 DOM 中,或者利用 CSS 混合模式来接近所需的颜色效果。现在,由于 SVG 的潜在救命功能,我们可以使用 SVG 滤镜来创建这些类似 Photoshop 的“调整图层”。
让我们开始 SaVinG!
分解 SVG
我们已经熟悉 SVG 的矢量优势。除了生成清晰、灵活、尺寸小的图形外,SVG 还支持 20 多种滤镜效果,允许我们对 SVG 文件进行模糊、变形以及更多操作。对于这种双色调效果,我们将使用两种滤镜来构建渐变映射。
feColorMatrix(可选)
feColorMatrix
效果允许我们根据 rbga
通道的矩阵来操作图像的颜色。Una Kravets 在 这篇深入探讨中详细介绍了使用 feColorMatrix
进行颜色操作,强烈建议阅读。
根据您的图像,可能需要通过使用颜色矩阵将其设置为灰度来平衡图像中的颜色。您可以根据需要调整 rbga
通道以获得所需的灰度效果。
<feColorMatrix type="matrix" result="grayscale"
values="1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
0 0 0 1 0" >
</feColorMatrix>
feComponentTransfer
接下来,使用 feComponentTransfer
滤镜效果将两种颜色映射到灰度图像的高光和阴影。对于此滤镜,需要注意一些特定的元素属性。
属性 | 作用 | 要使用的值 |
---|---|---|
color-interpolation-filters (必需) |
指定渐变插值、颜色动画和 Alpha 合成的颜色空间。 | sRGB |
result (可选) |
为该滤镜效果指定一个名称,该名称可以由另一个滤镜基元使用/引用,使用 in 属性。 |
duotone |
虽然 result
属性是可选的,但我喜欢将其包含进来,以便为每个滤镜提供更多上下文(并作为对未来参考的方便提示)。
feComponent
滤镜根据每个 rbga
组件的传递函数来处理颜色映射,这些传递函数被指定为父 feComponentTransfer
的子元素:feFuncR feFuncG feFuncB feFuncA
。我们使用这些 rbga
函数来计算渐变映射中两种颜色的值。
这是一个示例
上面屏幕截图中的 Peachy Pink 渐变映射使用了一种品红色(#bd0b91
),其值为 R(189) G(11) B(145)
。
将每个 RGB 值除以 255,得到矩阵中第一种颜色的值。第二列的 RGB 值得出 #fcbb0d
(金色)。与 Photoshop 中的渐变映射类似,第一种颜色(从左到右)映射到阴影,第二种颜色映射到高光。
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
<feFuncR type="table" tableValues="(189/255) 0.9882352941"></feFuncR>
<feFuncG type="table" tableValues="(11/255) 0.7333333333"></feFuncG>
<feFuncB type="table" tableValues="(145/255) 0.05098039216"></feFuncB>
<feFuncA type="table" tableValues="0 1"></feFuncA>
</feComponentTransfer>
步骤 3:使用 CSS 滤镜应用效果
SVG 滤镜完成之后,我们现在可以使用 CSS filter
属性并设置 url()
滤镜函数为 SVG 滤镜的 ID 来将其应用于图像。
值得注意的是,包含滤镜的 SVG 可以是隐藏在 HTML 中的元素。这样,它就会加载并可供使用,但不会在屏幕上渲染。
background-image: url('path/to/img');
filter: url(/path/to/svg/duotone-filters.svg#duotone_peachypink);
filter: url(#duotone_peachypink);
浏览器支持
您可能想知道这种技术支持情况如何,对吧?好吧,SVG 滤镜在浏览器中得到了很好的支持。
这些浏览器支持数据来自 Caniuse,其中包含更多详细信息。数字表示浏览器从该版本开始支持该功能。
桌面
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
8 | 3 | 10 | 12 | 6 |
移动设备/平板电脑
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
127 | 127 | 4.4 | 6.0-6.1 |
也就是说,CSS 滤镜的支持范围没有那么广。这意味着需要考虑一些优雅降级方案。
这些浏览器支持数据来自 Caniuse,其中包含更多详细信息。数字表示浏览器从该版本开始支持该功能。
桌面
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
18* | 35 | 否 | 79 | 6* |
移动设备/平板电脑
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
127 | 127 | 4.4* | 6.0-6.1* |
例如,Internet Explorer (IE) 不支持 CSS 滤镜 url()
函数,也不支持 CSS 背景混合模式,它是实现双色调效果的最佳替代方案。因此,IE 的回退方案可以在图像上使用绝对定位的 CSS 渐变叠加来模拟滤镜。
此外,在我最初在一个项目中实施这种方法时,在 Firefox 中,我遇到了根据 SVG 滤镜的路径访问滤镜本身的问题。Firefox 似乎只有在使用 SVG 文件的完整路径引用滤镜而不是单独使用滤镜 ID 时才能正常工作。这种情况似乎已经不再发生,但值得记住这一点。
整合所有内容
这是一个使用该滤镜的完整示例
<svg xmlns="http://www.w3.org/2000/svg">
<filter id="duotone_peachypink">
<feColorMatrix type="matrix" result="grayscale"
values="1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
0 0 0 1 0" >
</feColorMatrix>
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
<feFuncR type="table" tableValues="0.7411764706 0.9882352941"></feFuncR>
<feFuncG type="table" tableValues="0.0431372549 0.7333333333"></feFuncG>
<feFuncB type="table" tableValues="0.568627451 0.05098039216"></feFuncB>
<feFuncA type="table" tableValues="0 1"></feFuncA>
</feComponentTransfer>
</filter>
</svg>
这是应用于图像的效果

查看 CodePen 上 Lentie Ward (@lentilz) 编写的 双色调演示。
要了解更多示例,您可以在 这个笔中尝试更多双色调滤镜。
资源
以下资源是本文中使用技术的参考要点。
- SVG 过滤器基元元素 – MDN 文档
- 精通 feColorMatrix – Una Kravets 在 A List Apart 上的详细文章
这太有帮助了!谢谢!!
感谢分享! 我将在为我的 https://www.kodevelopers.com/5-server-tanitimi/ 网站创建横幅时使用这种技术! 你真是个救星。
首先:很棒的文章!
需要注意的是,如果您使用内联 SVG
<image>
标签,并直接使用其filter
属性应用过滤器,则可以提高浏览器支持。演示
☝️
我做了一个快速演示来测试(只在 IE 11 上测试过,但也应该在 10 上运行)
谢谢! 继续发布!
我最近不得不在一个项目中尝试创建这种效果。 我说这不可能。 显然我错了。
感谢这篇文章!