我爱上了SVG。当然,代码一开始看起来很密集和困难,但是当你了解它时,你会看到结果的美感。奖金是这些结果是代码,因此它可以连接到CMS。您的设计师可以轻松地知道他们不必为您网站上的每篇文章或产品重现效果。
今天我想告诉你我是如何想出这种玻璃文字效果的。
SVG可以承担很多,特别是当你刚刚开始学习它时(如果你是的话,Chris的书是一个很好的起点)。它实际上是一种全新的语言,特别是对于缺乏设计印章的人来说,有许多新技术和注意事项需要了解。但是,与HTML一样,您会发现我们可以使用一些工具来帮助使SVG更容易掌握。所以请耐心等待并继续尝试!
步骤0:耐心和空间
另外,给自己留出空间。从字面上看。SVG代码很密集所以我喜欢使用两三个新行来分隔出来。它使代码更容易阅读,并帮助我看到不同的部分是如何分离的,视觉分散较少。哦,并使用注释来标记您在文档中的位置。这可以帮助组织您的想法并记录您的发现。
我已经为学习这种玻璃效应的过程中的每一步做了演示,以帮助巩固我们正在进行的事情。
好了,既然我们已经做好了心理准备,那就让我们深入了解它吧!
步骤1:获取基本图像
首先要做的是:我们需要一个图像作为我们玻璃效果的背景。在这里,我们有一个<svg>
元素和一个元素<image>
。这类似于<img>
在HTML中添加。您会注意到SVG元素中viewBox
属性和<image>
元素的尺寸是相同的。这确保<image>
了与我们链接的实际图片的大小完全相同。
这是一个值得注意的关键区别:我们正在链接到图像。SVG文件本身不会绘制光栅图像,但我们可以在SVG代码中引用一个,并确保资产位于我们指向的位置。如果您以前使用过Adobe InDesign,那很像是链接到布局中的图像资源 – 图像是在InDesign布局中,但资产本身实际上存在于其他地方。
步骤2:扭曲图像
到目前为止直截了当,但这是事情变得复杂的地方,因为我们要为刚刚插入的图像添加一个过滤器。此过滤器将扭曲图像。如果仔细观察最后一步中的演示与此步骤中的演示之间的差异,您会发现图像中对象的边缘有点粗糙和波浪状。这是工作中的过滤器!
首先,我们创建另一个<svg>
来保持过滤器。这意味着如果我们想要重用我们的过滤器 – 例如在页面上的多个元素上 – 那么我们完全可以!
我们的第一个滤镜(#displacement
)会扭曲我们的形象。我们将使用feTurbulence
与feDisplacementMap
各萨拉Soueidan解释比我在这个岗位要好得多。Beau Jackson也写了一篇很好的文章,展示了如何使用它们来制作云效果。可以说,这两个过滤器往往会在一起,我喜欢把它们想象成什么东西需要出现“摇摆不定”。
使用我们的过滤器容器,我们只需要将该过滤器应用于我们的图像,其中包含魔法filter
属性<image>
!
<svg>
<!-- more stuff -->
<!-- DISTORTION IMAGE: clipped -->
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 clip-path="url(#clip)" filter= "url(#distortion)"></image>
<!-- FILTER: wobbly effect -->
<filter id="distortion">
<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/>
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="20" xChannelSelector="R" yChannelSelector="G"/>
</filter>
<!-- more stuff -->
</svg>
步骤3:剪辑文本
我们不希望整个图像被扭曲。我们要将扭曲<image>
的形状剪裁成某些文字的形状。这基本上是“通过”玻璃看到的图片部分。
要做到这一点,我们需要<text>
在a中添加一个元素<clip-path>
并给它一个id
。id
在clip-path
我们<image>
现在的称呼中将其形状限制为我们的形状<text>
。精彩!
步骤4:显示完整图像
好的,所以我们将扭曲的<image>
剪辑剪<text>
下来,但现在图像的其余部分都消失了。没有bueno。
我们可以通过在我们现有的之前添加相同<image>
但没有clip-path
或filter
属性的副本来抵消这种情况<image>
。这是我喜欢添加一些好评论以保持整洁的地方。这个想法就像在我们到目前为止的地方放置透明层。
<svg>我知道,我知道,这不是很整洁,我们正在重复自己。理想情况下,我们将直接在<text>
元素上设置滤镜,并使用in="BackgroundImage
属性feDisplacementMap
来扭曲文本背后的内容,而无需额外的元素。不幸的是,这对浏览器的支持很差,所以我们将使用多个图像。
<!-- more stuff -->
<!-- BACKGROUND IMAGE - visible -->
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 ></image>
<!-- DISTORTION IMAGE - clipped -->
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 clip-path="url(#clip)" filter= "url(#distortion)"></image>
<!-- more stuff -->
</svg>
步骤5:再次放置文本….
接下来,我们将复制我们的文本,就像我们在最后一步中对图像所做的那样。不幸的是,因为文本在a中clip-path
,所以它现在不可用于渲染。这是我们最后一次复制这样的内容,我保证!
现在我们应该看到一些看起来像普通图像的东西,上面有黑色文字。如果失真filter
就<image>
已经作出,我们已经是我们能看到“通过”玻璃,那么我们的新的<text>
将是玻璃本身。
<svg>
<!-- more stuff -->
<!-- TEXT - clipped -->
<clipPath id="clip">
<text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle">KYOTO</text>
</clipPath>
<!-- TEXT - visible -->
<text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle">KYOTO</text>
<!-- more stuff -->
</svg>
步骤6:创建文本的暗边
这是事情开始变得令人兴奋的地方,至少对我而言!
我们希望沿着文本元素创建一个黑色边缘,当与光边缘配对时(我们将看下一个),将增加文本外观对图像的深度。
我们想要一个新filter
的<text>
,所以让我们在我们的过滤器的SVG元素中创建一个并给它一个id="textFilter
并将它链接到元素的filter
属性<text>
。
SVG从背景到前景工作,所以我们在滤镜中放置的第一件事就是玻璃所具有的阴影,因为它是最远的。我会和你保持一致,这个很复杂,但我们要一步一步地完成它。
对于这个效果,我们使用四个过滤原语:feMorphology
,feOffset
,feFlood
和feComposite
。
feMorphology
是第一个。我们使用它来使文本变得更胖。在下面的演示,注释掉接下来的三个原语(feOffset
,feFlood
,feComposite
)并使用它。我有radius="4"
实现玻璃效果的价值,但看看如果将它设置为1 …或100会发生什么!
feOffset
用于feMorphology
在x轴或y轴上移动前一个图元()中的所有“像素” 。值dx="5"
和dy="5"
分别在x轴和y轴上移动“像素”。数字越大,移动越远。输入负数dx
,“像素”将向左移动。消极dy
,他们会向上移动!再次,当你玩它们时,你开始学习的东西。
我在“像素”周围引用的原因是因为它们不像您在CSS中所期望的那样是屏幕像素。相反,它们指的是我们在父级上设置的维度<svg>
。我认为它们是百分比。我们viewBox="0 0 1890 1260"
在示例中使用了这些设置。这意味着我们的<svg>
宽度为1890“像素”。如果我们设置dx="189"
它意味着我们将把我们的元素移动到SVG的10%(1890除以189)。
feFlood
是很棒的。如果你想用彩色填充屏幕,这是你需要的原始!您可能想知道为什么我们在应用它们时无法阅读我们的文本。那是因为您只能看到最后创建的过滤器基元的结果。每个先前原语的结果都与我们的<text>
元素有关。结果feFlood
就像它的名字:泛滥的颜色。它不知道你之前做过什么,也不关心 – 它只是用彩色填充一个区域。
这是一些人开始对SVG感到沮丧的地方。当你看不到它时,很难处理某些事情!相信我,当你使用SVG时,你会习惯这个。事实上,接下来的几个步骤将需要我们依赖于此并相信一切都仍然存在。
feComposite
将为我们解决这个问题。它有什么作用?MDN将其描述为:
该 SVG滤镜基元使用Porter-Duff合成操作之一在图像空间中以像素方式执行两个输入图像的组合:over,in,atop,out,xor和light。
那对我来说是jibba-jabba。我认为它影响in
了颜色/ alpha 的alpha层in2
。
有了这个,我们可以再次看到我们的文字拼写出来,因为我们使用的颜色略微透明,我们甚至可以看到扭曲的“玻璃”效果。大!
<svg>
<!-- more stuff -->
<!-- dark edge -->
<feMorphology operator="dilate" radius="4" in="SourceAlpha" result="dark_edge_01" />
<feConvolveMatrix order="3,3" kernelMatrix=
"1 0 0
0 1 0
0 0 1" in="dark_edge_01" result="dark_edge_02" />
<feOffset dx="5" dy="5" in="dark_edge_02" result="dark_edge_03"/>
<feFlood flood-color="rgba(0,0,0,.5)" result="dark_edge_04" />
<feComposite in="dark_edge_04" in2="dark_edge_03" operator="in" result="dark_edge" />
</filter>
<!-- more stuff -->
</svg>
步骤7:让我们做光边缘
这基本上与我们刚才所做的相同,但我们将使用负值dx
/ dy
值向上和向左移动形状。这次我们也设置了略带白色的颜色。我们的目标是获得很好的深度效果。
我们再次处于一个位置,我们可以看到的是过滤原语的最新结果,但我们看不到我们的黑暗边缘!feComposite
不是我们想用它们把它们组合在一起因为我们不希望黑边的alpha被光边染色……我们想看到两者!这导致我们……
<svg>
<filter id="textFilter">
<!-- more stuff -->
<feMorphology operator="dilate" radius="4" in="SourceAlpha" result="light_edge_01" />
<feConvolveMatrix order="3,3" kernelMatrix=
"1 0 0
0 1 0
0 0 1" in="light_edge_01" result="light_edge_02" />
<feOffset dx="-2" dy="-2" in="light_edge_02" result="light_edge_03"/>
<feFlood flood-color="rgba(255,255,255,.5)" result="light_edge_04" />
<feComposite in="light_edge_04" in2="light_edge_03" operator="in" result="light_edge" />
<!-- more stuff -->
</filter>
</svg>
步骤8:组合边缘
feMerge
!这是一个英雄。它允许我们获取任意数量的原始结果并合并它们,从而制作出新的图像。哇哦,我们现在可以看到黑暗和轻盈的边缘!
但是,我们确实希望它们是边缘而不是填满整个文本,因此我们需要删除原始文本<text>
占用的空间。我们接下来需要的是feComposite
砍掉原件的另一个SourceGraphic
。因为我们过去常常feMorphology
为我们的边缘填充字母,所以我们现在可以将原始字母形状从我们的结果中删除feMerge
。
<svg>
<filter id="textFilter">
<!-- more stuff -->
<feMerge result="edges">
<feMergeNode in="dark_edge" />
<feMergeNode in="light_edge" />
</feMerge>
<feComposite in="edges" in2="SourceGraphic" operator="out" result="edges_complete" />
</filter>
</svg>
现在我们开始看起来像玻璃,只缺少一件。
步骤9:是的,斜角
我们有一个非常好的3D外观玻璃效果。但是,这些字母看起来很平淡。让我们再添加一个效果,使它们看起来更圆润。
为了实现这一目标,我们将创造一个斜面效果。
首先我们要使用feGaussianBlur
。这将略微模糊我们现有的过滤器。我们将使用这个模糊的结果作为添加一些的基础feSpecularLighting
。像往常一样,随意玩这里的数字,看看你能得到什么效果!您可能想要更改的主要lighting-color
属性是属性。我们在这里使用的图像略暗,所以我们使用的是明亮的lighting-color
。如果您的图像非常明亮,这会使字母难以阅读,因此lighting-color
在这种情况下您可能会使用较暗的图像。
<svg>
<filter id="textFilter">
<!-- more stuff -->
<feGaussianBlur stdDeviation="5" result="bevel_blur" />
<feSpecularLighting result="bevel_lighting" in="bevel_blur" specularConstant="2.4" specularExponent="13" lighting-color="rgba(60,60,60,.4)">
<feDistantLight azimuth="25" elevation="40" />
</feSpecularLighting>
<feComposite in="bevel_lighting" in2="SourceGraphic" operator="in" result="bevel_complete" />
</filter>
</svg>
第10步:现在一切都在一起!
最后,在准备好所有部件之后,我们会做最后一件事feMerge
,为完成的效果准备好一切!
<svg>
<filter id="textFilter">
<!-- more stuff -->
<feMerge result="complete">
<feMergeNode in="edges_complete" />
<feMergeNode in="bevel_complete" />
</feMerge>
</filter>
</svg>
这里是一切,很好地间隔和评论:
<!-- VISIBLE SVG -->
<svg viewBox="0 0 1890 1260">
<!-- BACKGROUND IMAGE - visible -->
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 ></image>
<!-- DISTORTION IMAGE - clipped -->
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 clip-path="url(#clip)" filter= "url(#distortion)"></image>
<!-- TEXT - clipped -->
<clipPath id="clip">
<text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle">KYOTO</text>
</clipPath>
<!-- TEXT - visible -->
<text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle" filter="url(#textFilter)">KYOTO</text>
</svg>
<!-- FILTERS -->
<svg>
<filter id="distortion">
<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/>
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="20" xChannelSelector="R" yChannelSelector="G"/>
</filter>
<filter id="textFilter">
<!-- dark edge -->
<feMorphology operator="dilate" radius="4" in="SourceAlpha" result="dark_edge_01" />
<feOffset dx="5" dy="5" in="dark_edge_01" result="dark_edge_03"/>
<feFlood flood-color="rgba(0,0,0,.5)" result="dark_edge_04" />
<feComposite in="dark_edge_04" in2="dark_edge_03" operator="in" result="dark_edge" />
<!-- light edge -->
<feMorphology operator="dilate" radius="4" in="SourceAlpha" result="light_edge_01" />
<feOffset dx="-2" dy="-2" in="light_edge_01" result="light_edge_03"/>
<feFlood flood-color="rgba(255,255,255,.5)" result="light_edge_04" />
<feComposite in="light_edge_04" in2="light_edge_03" operator="in" result="light_edge" />
<!-- edges together -->
<feMerge result="edges">
<feMergeNode in="dark_edge" />
<feMergeNode in="light_edge" />
</feMerge>
<feComposite in="edges" in2="SourceGraphic" operator="out" result="edges_complete" />
<!-- bevel -->
<feGaussianBlur stdDeviation="5" result="bevel_blur" />
<feSpecularLighting result="bevel_lighting" in="bevel_blur" specularConstant="2.4" specularExponent="13" lighting-color="rgba(60,60,60,.4)">
<feDistantLight azimuth="25" elevation="40" />
</feSpecularLighting>
<feComposite in="bevel_lighting" in2="SourceGraphic" operator="in" result="bevel_complete" />
<!-- everything in place -->
<feMerge result="complete">
<feMergeNode in="edges_complete" />
<feMergeNode in="bevel_complete" />
</feMerge>
</filter>
</svg>