SVG和CSS打造逼真云朵效果
希腊神话中,宙斯创造了云仙女涅菲勒。和其它希腊神话一样,这个故事相当离奇。这里是一个简短且合适的版本:
传说中,涅菲勒是宙斯以自己美丽妻子的形象创造的。一位凡人邂逅涅菲勒,爱上了她,他们一起……最终,不可思议的是,这朵云诞下了半人半马的半人马婴儿。
很奇怪,对吧?我个人也无法理解。幸运的是,在浏览器中创建云朵的过程要简单得多,也正经得多。
最近,我发现开发者Yuan Chuan实现了代码生成的、逼真的云朵效果。对我来说,这种在浏览器中实现的效果曾经是神话故事。
只需浏览一下这个示例代码,我们就能想象到,通过使用带有<filter></filter>
元素(包含两个SVG滤镜)的CSS box-shadow
,可以实现令人信服的单个云朵效果。
我们想要的逼真效果是通过feTurbulence
和feDisplacementMap
的巧妙结合实现的。这些SVG滤镜功能强大、复杂且提供了非常令人兴奋的功能(包括一个奥斯卡获奖算法!)。然而,其底层复杂性可能会让人望而生畏。
虽然SVG滤镜的物理原理超出了本文的范围,但在MDN和w3.org上提供了大量的文档。关于feTurbulence
和feDisplacementMap
的非常有益的页面是免费提供的(并且作为这本精彩书籍的一个章节)。
在本文中,我们将专注于学习如何使用这些SVG滤镜来获得惊人的效果。我们不需要深入了解幕后算法的运作方式,就像艺术家不需要了解颜料的分子结构就能渲染出令人惊叹的风景一样。
相反,让我们密切关注几个对在浏览器中绘制令人信服的云朵至关重要的SVG属性。使用这些属性,我们可以将这些强大的滤镜运用自如,并学习如何在自己的项目中精确地自定义它们。
从基础开始
CSS box-shadow
属性有五个值得关注的值:
<code>box-shadow: <offsetx><offsety><blurradius><spreadradius><color>;</color></spreadradius></blurradius></offsety></offsetx></code>
让我们将这些值调高(可能高于任何理智的开发者会使用的值),这样阴影本身就会成为舞台上的一个角色。
<code>#cloud-square { background: turquoise; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; } #cloud-circle { background: coral; border-radius: 50%; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; }</code>
你玩过或者见过影子戏吗?
就像用手改变形状来改变阴影一样,我们HTML中的“源形状”可以移动和变形来移动和改变在浏览器中渲染的阴影的形状。box-shadow
复制了原始大小和border-radius
上的“变形”功能。SVG滤镜同时应用于元素及其阴影。
<code><svg height="0" width="0"><filter><feturbulence basefrequency=".01" numoctaves="10" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="10"></fedisplacementmap></filter></svg></code>
这是我们目前SVG的标记。它不会渲染,因为我们还没有定义任何视觉效果(更不用说零宽度和高度了)。它的唯一目的是保存一个滤镜,我们将这个滤镜提供给我们的SourceGraphic
(也就是我们的<div>)。我们的源<code><div>及其阴影都由滤镜独立扭曲。我们将添加必要的CSS规则,使用其ID将HTML元素(<code>#cloud-circle
)链接到SVG滤镜:
<code>#cloud-circle { filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; }</code>
瞧!
好吧,承认吧,添加SVG滤镜相当不起眼。
别担心!我们只是触及了表面,还有很多好东西要看。
实验feDisplacementMap
的scale
属性
对这个属性进行一些非科学的实验可以产生戏剧性的效果。目前,让我们保持feTurbulence
中的所有值不变,只需调整DisplacementMap
的scale
属性。
随着scale
值的增加(以30为增量),我们的源<div>会发生扭曲,并投射出阴影来反映云朵在天空中的随机形态。
<pre class="brush:php;toolbar:false"><code><fedisplacementmap in="SourceGraphic" scale="180"></fedisplacementmap></code></pre>
<p>好了,我们有所进展!让我们稍微改变一下颜色,以产生更令人信服的云朵效果,并增强效果。</p>
<pre class="brush:php;toolbar:false"><code>body {
background: linear-gradient(165deg, #527785 0%, #7FB4C7 100%);
}
#cloud-circle {
width: 180px;
height: 180px;
background: #000;
border-radius: 50%;
filter: url(#filter);
box-shadow: 200px 200px 50px 0px #fff;
}</code></pre>
<p>现在我们更接近逼真的云朵效果了!</p>
<h3 id="修改-code-box-shadow-code-的-code-blur-code-值">修改<code>box-shadow
的blur
值
下面的图像系列显示了blur
值对box-shadow
的影响。在这里,blur
值以10像素为增量增加。
为了使我们的云朵具有一些积云般的效果,我们可以稍微加宽我们的源<div>。
<pre class="brush:php;toolbar:false"><code>#cloud-circle {
width: 500px;
height: 275px;
background: #000;
border-radius: 50%;
filter: url(#filter);
box-shadow: 200px 200px 60px 0px #fff;
}</code></pre>
<p>等等!我们加宽了源元素,现在它挡住了我们称之为云朵的白色阴影。让我们将阴影“重新投射”到更远的距离,这样我们的云朵就不会被源图像遮挡。(可以想象一下,将你的手从墙上移开,这样就不会挡住影子戏的视线。)</p>
<p>这可以通过一些CSS定位轻松实现。<code><div>是云朵的父元素,默认情况下是静态定位的。让我们用一些绝对定位将我们的源<code><div>“塞”起来并移出文档流。最初,这也会重新定位我们的阴影,因此我们还需要增加阴影与元素的距离,并稍微调整元素的位置。
<pre class="brush:php;toolbar:false"><code>#cloud-circle {
width: 500px;
height: 275px;
background: #000;
border-radius: 50%;
filter: url(#filter);
box-shadow: 400px 400px 60px 0px #fff; /* 增加阴影偏移量 */
position: absolute; /* 将父元素移出文档流 */
top: -320px; /* 向下移动 */
left: -320px; /* 向右移动 */
}</code></pre>
<p>是的!我们已经得到了一个相当令人信服的云朵。</p>
<p>渲染到浏览器中的图像对云朵的描绘相当不错——但是,我不确定……这朵云真的能体现云仙女涅菲勒吗?我相信我们可以做得更好!</p>
<h3 id="使用图层表达深度">使用图层表达深度</h3>
<p>这就是我们想要的:</p>
<p>从这张照片中云朵的深度、纹理和丰富性来看,有一点很清楚:宙斯上过美术学校。至少,他一定读过《设计的普遍原则》,其中阐述了一个强大而看似普通的概念:</p>
<blockquote>
<p>[…] 照明偏差在深度和自然感的解释中起着重要作用,并且可以通过设计师以各种方式进行操作……使用光暗区域之间的对比度来改变深度的外观。</p>
</blockquote>
<p>这段话为我们提供了一个线索,说明我们如何才能大大改进我们自己生成的云朵代码。我们可以通过将不同形状、大小和颜色的图层堆叠在一起,来渲染出与参考图像中的云朵高度相似的云朵。这只需要根据需要多次调用我们的滤镜即可。</p>
<pre class="brush:php;toolbar:false"><code><svg height="0" width="0"><filter><feturbulence basefrequency="0.012" numoctaves="4" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="170"></fedisplacementmap></filter><filter><feturbulence basefrequency="0.012" numoctaves="2" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="150"></fedisplacementmap></filter><filter><feturbulence basefrequency="0.012" numoctaves="2" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="100"></fedisplacementmap></filter></svg></code></pre>
<p>应用我们的图层将使我们有机会探索<code>feTurbulence
并实现其多功能性。我们将选择可用的更平滑的类型:fractalNoise
,并将numOctaves
调高到6。
<code><feturbulence basefrequency="n" numoctaves="6" type="fractalNoise"></feturbulence></code>
这意味着什么?现在,让我们重点关注baseFrequency
属性。以下是我们增加n的值时得到的结果:
诸如湍流、噪声、频率和倍频程之类的词语可能显得奇怪甚至令人困惑。但是别担心!将这个滤镜的效果比作声波实际上是完全准确的。我们可以将低频(baseFrequency=0.001
)与低沉的噪声联系起来,并将高频(baseFrequency=0.1
)与更高、更清晰的音调联系起来。
我们可以看到,对于积云般的效果,baseFrequency
的值可能舒适地位于~0.005和~0.01范围内。
使用numOctaves
添加细节
递增numOctaves
允许我们以极其精细的细节来渲染图像。这需要大量的计算,因此请注意:高值会严重影响性能。除非你的浏览器戴着头盔和护膝,否则尽量避免提高这个值。
好消息是,我们不需要将这个值调得太高就能产生细节和精细度。如上图所示,我们可以将numOctaves
值设置为4或5。
结果如下
使用seed
属性实现无限变化
关于seed
属性有很多内容需要说明,因为它暗示了幕后发生的魔法。但是,就我们的目的而言,seed
的效用可以用四个字概括:“不同的值,不同的形状”。
Perlin噪声函数(前面提到过)使用此值作为其随机数生成器的起点。选择不包含此属性将默认seed
为零。但是,如果包含此属性,无论我们赋予seed
什么值,都不需要担心性能问题。
上面的GIF代表了seed
提供的一些功能。请记住,每一朵云都是一个分层的复合云。(虽然我已经调整了每个图层的属性,但我保持了它们各自的seed
值一致。)
在这里,仔细观察参考图像,我已经将3个云<div>(不透明度不同)叠加到一个基础<code><div>上。通过反复试验和输入任意<code>seed
值,我最终得到了一个类似于照片中云朵形状的形状。
天马行空
当然,认为我们绘制到浏览器上的<div>会优于宙斯的涅菲勒,那将是狂妄自大。然而,我们能够从CSS和SVG滤镜中挖掘出越多的奥秘,我们就越有能力创造出视觉上令人惊叹的东西,并且与雷神最初的创造高度相似。然后,我们可以继续进行进一步的实验!
<p>反射雾气</p>
<p>高层卷云</p>
<p>在本文中,我们只是涉足了一个充满力量和复杂性的海洋。SVG滤镜通常看起来令人不知所措且难以接近。</p>
<p>然而,就像A Single Div项目中的示例或Diana Smith的绘画技巧一样,一种轻松愉快的实验方法总是会带来惊人的结果!</p>
<h4 id="成就解锁-涅菲勒云朵生成器">成就解锁!涅菲勒云朵生成器</h4>
<p>我相信你们很多人很乐意深入了解制作云朵所需的所有技术细节,但可能更喜欢一些更方便在项目中使用云朵的方法。我开发了一个小工具来帮助生成云朵并实验形状和变化。</p>
<p>生成云朵!</p>
<p>有任何问题、建议或意见?请在Twitter上联系我,或在此帖中发表评论。</p>
<p><small>非常感谢Amelia Bellamy-Royds对本文提出的宝贵建议。</small></p>
</div>
以上是用SVG和CSS绘制逼真的云的详细内容。更多信息请关注PHP中文网其他相关文章!

对于Astro,我们可以在构建过程中生成大部分网站,但是有一小部分服务器端代码可以使用Fuse.js之类的搜索功能来处理搜索功能。在此演示中,我们将使用保险丝搜索一组个人“书签”


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

WebStorm Mac版
好用的JavaScript开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版