用 css 和 svg 绘制一朵“真实”的云
用 css 和 svg 绘制一朵“真实”的云
本文根据文章 Drawing Realistic Clouds with SVG and CSS,仅记录自己学习过程。
最终实现效果:
首先,CSS的box-shadow属性有五个值:
1 |
|
值 | 描述 |
---|---|
h-shadow | 必需。水平阴影的位置。允许负值。 |
v-shadow | 必需。垂直阴影的位置。允许负值。 |
blur | 可选。模糊距离。 |
spread | 可选。阴影的尺寸。 |
color | 可选。阴影的颜色。 |
inset | 可选。将外部阴影 (outset) 改为内部阴影。 |
我们把这些值调高,就会得到类似影子木偶的效果:
就像一只手改变形状可以改变投影一样,我们改变HTML的“源形状”也可以使渲染在浏览器中的投影变形。box-shadow
复制了原始尺寸和border-radius
上的“渐变”特性,SVG过滤器则同时应用于元素及其阴影。
1 |
|
这是我们目前的SVG代码,它不会被渲染,因为我们还没有定义任何可见的东西。它唯一的目的就是保存我们为SourceGraphic
(也就是我们的<div>
)提供的过滤器。
借助SVG过滤器的ID,通过添加CSS规则将HTML元素 #cloud-circle 和SVG过滤器进行关联:
1 |
|
差不多就是这样:
尝试使用feDisplacementMap的scale属性
使用这一属性进行一些非科学试验可以产生显著的效果。现在,我们保持feTurbulence
的值不变,简单调整feDisplacementMap
的scale
属性值。
随着scale
的增加(以30为增量),我们的源<div>
变得扭曲,投射的阴影反应出天空中云出现的随机形式。
1 |
|
好了,我们有进展了!让我们稍微改变颜色,以形成更具说服力的云。
1 |
|
修改box-shadow的模糊度
下面一套图片展示了box-shadow
属性的模糊度作用的效果,这里,我们以10px递增模糊值:
为了增加一点积云的效果,我们可以稍微扩宽源<div>
的宽度:
1 |
|
等等,我们扩宽了源元素的宽度,但它现在遮挡在我们云层(白色阴影)的上方。让我们在更远的位置重新投影,这样我们的云就不会再被源图像遮挡了(你可以想象成把你的手往远离墙的方向移动,这样它就不会挡住你的影子木偶的视线了)。
这点我们通过CSS定位可以很好地实现。<body>
是父元素,默认是静态定位的,我们给源<div>
添加绝对定位。最初地,这也会重新定位我们的阴影,因此我们还需要增加阴影和元素之间的距离。
1 |
|
现在我们已经实现了一个极具说服力的云
通过层次传达深度
这是我们想要的效果:
从这张照片中云层的深度、纹理和丰富性来看,宙斯一定是读过艺术专业的。至少,他一定读过《通用设计法则》,这本书阐述了一个强大而又普通的概念:照明偏差在深度和自然度的解释中起着重要作用,设计师可以通过多种方式操纵照明偏差,利用明暗区域之间的对比度来改变深度的外观。
这段话给了我们一个提示,我们可以将不同形状、大小和颜色的图层堆叠在一起,可以实现像参考图片中那样具有高保真度的云。我们要做的也只是多次调用SVG过滤器。
使用三个SVG过滤器绘制前中后三朵云:
1 |
|
通过分层的应用,我们有机会去探索feTurbulence并认识它的多样性。我们选择了较为平滑的类型:fractalNoise,对于numOctaves的值最高只调到了6。
上面这些意味着什么?我们来看一下baseFrequency这个属性,下面几张图片是不同baseFrequency值下的效果。
从效果看,介于0.005~0.01的值比较符合我们想要的积云效果。
用numOctaves添加细节。
增加numOctaves值允许我们以更细的粒度去渲染图像,这个过程需要大量的计算,因此需要注意:高值会严重影响性能。
我们不需要为达到精细的效果而设置太高的值,介于4~5就够了。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!