搜索
首页web前端css教程用SVG和CSS绘制逼真的云

SVG和CSS打造逼真云朵效果

Drawing Realistic Clouds with SVG and CSS

希腊神话中,宙斯创造了云仙女涅菲勒。和其它希腊神话一样,这个故事相当离奇。这里是一个简短且合适的版本:

传说中,涅菲勒是宙斯以自己美丽妻子的形象创造的。一位凡人邂逅涅菲勒,爱上了她,他们一起……最终,不可思议的是,这朵云诞下了半人半马的半人马婴儿。

很奇怪,对吧?我个人也无法理解。幸运的是,在浏览器中创建云朵的过程要简单得多,也正经得多。

最近,我发现开发者Yuan Chuan实现了代码生成的、逼真的云朵效果。对我来说,这种在浏览器中实现的效果曾经是神话故事。

只需浏览一下这个示例代码,我们就能想象到,通过使用带有<filter></filter>元素(包含两个SVG滤镜)的CSS box-shadow,可以实现令人信服的单个云朵效果。

我们想要的逼真效果是通过feTurbulencefeDisplacementMap的巧妙结合实现的。这些SVG滤镜功能强大、复杂且提供了非常令人兴奋的功能(包括一个奥斯卡获奖算法!)。然而,其底层复杂性可能会让人望而生畏。

虽然SVG滤镜的物理原理超出了本文的范围,但在MDN和w3.org上提供了大量的文档。关于feTurbulencefeDisplacementMap的非常有益的页面是免费提供的(并且作为这本精彩书籍的一个章节)。

在本文中,我们将专注于学习如何使用这些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滤镜相当不起眼。

别担心!我们只是触及了表面,还有很多好东西要看。

实验feDisplacementMapscale属性

对这个属性进行一些非科学的实验可以产生戏剧性的效果。目前,让我们保持feTurbulence中的所有值不变,只需调整DisplacementMapscale属性。

随着scale值的增加(以30为增量),我们的源<div>会发生扭曲,并投射出阴影来反映云朵在天空中的随机形态。 <pre class="brush:php;toolbar:false">&lt;code&gt;&lt;fedisplacementmap in=&quot;SourceGraphic&quot; scale=&quot;180&quot;&gt;&lt;/fedisplacementmap&gt;&lt;/code&gt;</pre> <p>好了,我们有所进展!让我们稍微改变一下颜色,以产生更令人信服的云朵效果,并增强效果。</p> <pre class="brush:php;toolbar:false">&lt;code&gt;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; }&lt;/code&gt;</pre> <p>现在我们更接近逼真的云朵效果了!</p> <h3 id="修改-code-box-shadow-code-的-code-blur-code-值">修改<code>box-shadowblur

下面的图像系列显示了blur值对box-shadow的影响。在这里,blur值以10像素为增量增加。

为了使我们的云朵具有一些积云般的效果,我们可以稍微加宽我们的源<div>。 <pre class="brush:php;toolbar:false">&lt;code&gt;#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 60px 0px #fff; }&lt;/code&gt;</pre> <p>等等!我们加宽了源元素,现在它挡住了我们称之为云朵的白色阴影。让我们将阴影“重新投射”到更远的距离,这样我们的云朵就不会被源图像遮挡。(可以想象一下,将你的手从墙上移开,这样就不会挡住影子戏的视线。)</p> <p>这可以通过一些CSS定位轻松实现。<code><div>是云朵的父元素,默认情况下是静态定位的。让我们用一些绝对定位将我们的源<code><div>“塞”起来并移出文档流。最初,这也会重新定位我们的阴影,因此我们还需要增加阴影与元素的距离,并稍微调整元素的位置。 <pre class="brush:php;toolbar:false">&lt;code&gt;#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; /* 向右移动 */ }&lt;/code&gt;</pre> <p>是的!我们已经得到了一个相当令人信服的云朵。</p> <p>渲染到浏览器中的图像对云朵的描绘相当不错——但是,我不确定……这朵云真的能体现云仙女涅菲勒吗?我相信我们可以做得更好!</p> <h3 id="使用图层表达深度">使用图层表达深度</h3> <p>这就是我们想要的:</p> <p>从这张照片中云朵的深度、纹理和丰富性来看,有一点很清楚:宙斯上过美术学校。至少,他一定读过《设计的普遍原则》,其中阐述了一个强大而看似普通的概念:</p> <blockquote> <p>[…] 照明偏差在深度和自然感的解释中起着重要作用,并且可以通过设计师以各种方式进行操作……使用光暗区域之间的对比度来改变深度的外观。</p> </blockquote> <p>这段话为我们提供了一个线索,说明我们如何才能大大改进我们自己生成的云朵代码。我们可以通过将不同形状、大小和颜色的图层堆叠在一起,来渲染出与参考图像中的云朵高度相似的云朵。这只需要根据需要多次调用我们的滤镜即可。</p> <pre class="brush:php;toolbar:false">&lt;code&gt;&lt;svg height=&quot;0&quot; width=&quot;0&quot;&gt;&lt;filter&gt;&lt;feturbulence basefrequency=&quot;0.012&quot; numoctaves=&quot;4&quot; type=&quot;fractalNoise&quot;&gt;&lt;/feturbulence&gt;&lt;fedisplacementmap in=&quot;SourceGraphic&quot; scale=&quot;170&quot;&gt;&lt;/fedisplacementmap&gt;&lt;/filter&gt;&lt;filter&gt;&lt;feturbulence basefrequency=&quot;0.012&quot; numoctaves=&quot;2&quot; type=&quot;fractalNoise&quot;&gt;&lt;/feturbulence&gt;&lt;fedisplacementmap in=&quot;SourceGraphic&quot; scale=&quot;150&quot;&gt;&lt;/fedisplacementmap&gt;&lt;/filter&gt;&lt;filter&gt;&lt;feturbulence basefrequency=&quot;0.012&quot; numoctaves=&quot;2&quot; type=&quot;fractalNoise&quot;&gt;&lt;/feturbulence&gt;&lt;fedisplacementmap in=&quot;SourceGraphic&quot; scale=&quot;100&quot;&gt;&lt;/fedisplacementmap&gt;&lt;/filter&gt;&lt;/svg&gt;&lt;/code&gt;</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中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
模拟鼠标运动模拟鼠标运动Apr 22, 2025 am 11:45 AM

如果您曾经在现场演讲或课程中必须显示一个互动动画,那么您可能知道它并不总是那么容易与您的幻灯片进行互动

通过Astro Action和Fuse.js为搜索提供动力通过Astro Action和Fuse.js为搜索提供动力Apr 22, 2025 am 11:41 AM

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

未定义:第三个布尔值未定义:第三个布尔值Apr 22, 2025 am 11:38 AM

我想在我的一个项目中实现一条通知消息,类似于您在保存文档时在Google文档中看到的信息。换句话说,一个

捍卫三元声明捍卫三元声明Apr 22, 2025 am 11:25 AM

几个月前,我正在使用黑客新闻(就像一个人一样),并且遇到了一篇(现已删除的)文章,内容涉及不使用if语句。如果您是这个想法的新手(就像我

使用网络语音API进行多语言翻译使用网络语音API进行多语言翻译Apr 22, 2025 am 11:23 AM

自科幻小说以来,我们就幻想着与我们交谈的机器。今天这很普遍。即便如此,制造的技术

JetPack Gutenberg块JetPack Gutenberg块Apr 22, 2025 am 11:20 AM

我记得当古腾堡被释放到核心时,因为那天我在WordCamp我们。现在已经过去了几个月,所以我想我们越来越多的人

在VUE中创建可重复使用的分页组件在VUE中创建可重复使用的分页组件Apr 22, 2025 am 11:17 AM

大多数Web应用程序背后的想法是从数据库中获取数据,并以最佳方式将其呈现给用户。当我们处理数据时

使用'盒子阴影”和剪辑路径一起使用'盒子阴影”和剪辑路径一起Apr 22, 2025 am 11:13 AM

让我们对您可以做一些有意义的事情做一些逐步的情况,但是您仍然可以用CSS欺骗来完成它。在这个

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

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

热工具

mPDF

mPDF

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

SublimeText3 英文版

SublimeText3 英文版

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

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版