原文:Drawing Realistic Clouds with SVG and CSS

这是作者最终实现的效果:

......哦,不,应该是这张: 在线查看效果:cloud demo

正文开始啦~

希腊神话讲述了一个关于宙斯创造云女神涅斐勒的故事。和其他希腊神话一样,这个故事极其怪异并且有点限制级。下面的表述则是一个比较简短且含蓄的版本(限制级,非战斗人员请撤离)。

涅斐勒(云神),据说是宙斯按照自己美丽妻子的形象创造的。传说有个凡人遇见了涅斐勒,一见钟情爱上了她并且在一起了,后来她们一起睡了一个觉,然后奇怪的事情发生了,一朵云生下了一个半人半马的小孩,传说这就半人马的祖先。

很不可思议对吗?就我个人而言,我搞不懂。但庆幸的是,浏览器中创建云的过程要简单得多,也没有那么不可描述。

这是@袁川画的云demo

最近,我发现开发者 @袁川 已经用代码实现了仿真的云烟。对我来说,在浏览器中实现一直是个神话。

通过简单扫一下这个demo里面的代码,我们可以现象,逼真而又独特的云朵是可以通过使用cssbox-shadow和一个包含两个元素的SVG过滤器<filter>去实现。

我们想要的仿真效果是通过feTurbulencefeDisplacementMap之间的微妙混合来实现的。SVG过滤器功能强大、复杂,并且提供了令人非常兴奋的功能(还包括奥斯卡获奖算法)。然而,在它的底层,它们的复杂性可能有点吓人!

译者:奥斯卡获奖算法,这么牛逼?无知限制了我的想象。

虽然SVG的物理特性超出了本文的范畴,但是在MDN和w3.org上有大量的文档。一个免费的关于feTurbulencefeDisplacement非常有用的页面(同时被作为这本惊奇的书的一个章节)

对于本文,我们专注学习如何使用SVG的过滤器实现惊人的效果。我们不需要深入研究其底层的算法,正如艺术家不需要了解涂漆的分子结构也能绘出令人惊叹的风景一样。

先从一些基础开始

CSS的box-shadow属性有五个值需要搞懂:

box-shadow: <offsetX> <offsetY> <blurRadius> <spreadRadius> <color>;
复制代码

让我们把这些值调高(可能比任何理智的开发人员调得都要高):

#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;
}
复制代码

会得到下面的效果图:

你曾经应该也玩过或者看过影子木偶对吗?像下面这样:

译者:看见这个,想起小时候自己也玩过, 两个拇指叉在一块能摆出鸽子的投影。

就像一只手改变形状可以改变投影一样,我们改变HTML的“源形状”也可以使渲染在浏览器中的投影变形。box-shadow复制了原始尺寸和border-radius上的“渐变”特性,SVG过滤器则同时应用于元素及其阴影。

<svg width="0" height="0"> <filter id="filter"><feTurbulence type="fractalNoise" baseFrequency=".01" numOctaves="10" /><feDisplacementMap in="SourceGraphic" scale="10" /></filter>
</svg>
复制代码

这是我们目前的SVG代码,它不会被渲染,因为我们还没有定义任何可见的东西。它唯一的目的就是保存我们为SourceGraphic(也就是我们的<div>)提供的过滤器。

我们借助SVG过滤器的ID,通过添加CSS规则将HTML元素(#cloud-circle)和SVG过滤器进行关联:

#cloud-circle {filter: url(#filter);box-shadow: 200px 200px 50px 0px #fff;
}
复制代码

嗯!很棒,就是这样

在线查看demo

别急!我们只是了解了皮毛,还有很多好东西要看。

尝试使用feDisplacementMap的scale属性

使用这一属性进行一些非科学试验可以产生显著的效果。现在,我们保持feTurbulence的值不变,简单调整feDisplacementMapscale属性值。

随着scale的增加(以30为增量),我们的源<div>变得扭曲,投射的阴影反应出天空中云出现的随机形式。

<feDisplacementMap in="SourceGraphic" scale="180"/>
复制代码

在线查看demo

好了,我们有进展了!让我们稍微改变颜色,以形成更具说服力的云。

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;
}
复制代码

现在,我们越来越接近真实的云朵效果了!

修改box-shadow的模糊度

下面一套图片展示了box-shadow属性的模糊度作用的效果,这里,我们以10px递增模糊值:

随着模糊值增加,云朵也变得更加柔和。

为了增加一点积云的效果,我们可以稍微扩宽源<div>的宽度:

#cloud-circle {width: 500px; height: 275px;background: #000;border-radius: 50%;filter: url(#filter);box-shadow: 200px 200px 60px 0px #fff;
}
复制代码

很好,我们的源元素开始碍事了?

等等,我们扩宽了源元素的宽度,但它现在遮挡在我们云层(白色阴影)的上方。让我们在更远的位置重新投影,这样我们的云就不会再被源图像遮挡了(你可以想象成把你的手往远离墙的方向移动,这样它就不会挡住你的影子木偶的视线了)。

这点我们通过CSS定位可以很好地实现。<body>是父元素,默认是静态定位的,我们给源<div>添加绝对定位。最初地,这也会重新定位我们的阴影,因此我们还需要增加阴影和元素之间的距离。

#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;
}
复制代码

是的,我们已经实现了一个极具说服力的云:这里查看

浏览器上展示的已经是一个相当完美的云了,但我不确定......这片云真的能公正地描述云女神涅斐勒吗?我相信我们还可以做得更好!

通过层次传达深度

这是我们想要的效果:

从这张照片中云层的深度、纹理和丰富性来看,宙斯一定是读过艺术专业的。至少,他一定读过《通用设计法则》,这本书阐述了一个强大而又普通的概念:

照明偏差在深度和自然度的解释中起着重要作用,设计师可以通过多种方式操纵照明偏差,利用明暗区域之间的对比度来改变深度的外观。

这段话给了我们一个提示,我们可以将不同形状、大小和颜色的图层堆叠在一起,可以实现像参考图片中那样具有高保真度的云。我们要做的也只是多次调用SVG过滤器。

使用三个SVG过滤器绘制前中后三朵云:

<svg width="0" height="0"><!-- 后层 --><filter id="filter-back"><feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="4" /><feDisplacementMap  in="SourceGraphic" scale="170" /></filter><!-- 中层 --><filter id="filter-mid"><feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" /><feDisplacementMap  in="SourceGraphic" scale="150" /></filter><!-- 前层 --><filter id="filter-front"><feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" /><feDisplacementMap  in="SourceGraphic" scale="100" /></filter>
</svg>
复制代码

通过分层的应用,我们有机会去探索feTurbulence并认识它的多样性。我们选择了较为平滑的类型:fractalNoise,对于numOctaves的值最高只调到了6。

上面这些意味着什么?我们来看一下baseFrequency这个属性,下面几张图片是不同baseFrequency值下的效果:

值越低,图像就越圆,越模糊。

从效果看,介于0.005~0.01的值比较符合我们想要的积云效果。

用numOctaves添加细节

增加numOctaves值允许我们以更细的粒度去渲染图像,这个过程需要大量的计算,因此需要注意:高值会严重影响性能。

numOctaves的值设置得越高,云的效果就越精细。

幸运的是我们不需要为达到精细的效果而设置太高的值,介于4~5就够了。

最后的效果

查看效果

用seed属性进行无限变形

关于seed属性有很多可以说,但就我们的目的而言,seed的作用可以归结为:不同的值,不同的形状

柏林噪音函数使用这个值作为其随机数生成器的起点。选择不包含此属性则将seed值默认为0;当包含时,无论我们设置何值,都不需要担心会影响性能。

不同的seed值,对应生成不同的形状。

上面的GIF代表了seed作用的效果。请记住,每个云都是分层的复合云(虽然我调整了每一层的属性,但我保持了它们的seed值一致)。

仔细观察上面这张参考图片,我将3个云层<div>堆砌在一个基础的div上,通过反复试验不同的seed值,最终得到了与图中比较相似的形状。如下图:

在线查看demo

天空的极限

显然,认为我们用<div>在浏览器上绘制的云比涅斐勒高级是很荒谬的。

但是,我们能够梳理出CSS和SVG过滤器的神秘感越多,我们就越有能力去创造在视觉上令人惊叹的东西,并且高度保真于雷神的创作。那么,我们可以做进一步的试验了!

  • 反射雾
  • 高层云

在这篇文章中,我们刚刚涉足了一个充满力量和复杂性的知识海洋,SVG过滤器通常看起来复杂地难以理解。

不过,就像A Single Div Project和Smith's绘画技术中的例子一样,有趣和实验性的方法总会给人惊艳的效果。

我希望这篇文章能让你对web上进行摄影写实开发感到兴奋,欢迎下方评论交流你的想法~

转载于:https://juejin.im/post/5d11df99e51d454d544abf8a

【译】来,用 SVG CSS 给你画一朵真实的云相关推荐

  1. 用css给我画一朵花

    好的,那么我们可以用 CSS 中的 ::before 和 ::after 伪元素来画一朵花. 首先,我们需要定义一个元素作为花的容器,并给它一个高度和宽度.然后,我们可以在这个元素的 ::before ...

  2. 如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报(可控制速度)

    因为平时也关注网易UEDC的订阅号,前几天就看到了这么一个动效,主题是<网易云音乐2018年度听歌报告>,内容是一个人在努力蹬车因为构图简单,创意又不错,所以就试了下用SVG+CSS动画实 ...

  3. [译] JavaScript 中的 CSS:基于组件的样式的未来

    本文讲的是[译] JavaScript 中的 CSS:基于组件的样式的未来, 原文地址:CSS in JavaScript: The future of component-based styling ...

  4. php绘制一个三角形,如何利用css或html5画出一个三角形?两种不同的制作三角形方法(代码实例)...

    我们在平时的前端开发的时候,有时候是需要一些小图形来丰富一下页面效果,比如:下拉列表的倒三角图形.那么这样的一个三角形是如何制作出来的,本章给大家介绍如何利用css或html画出一个三角形?两种不同的 ...

  5. [css] 使用css3画一个扇形

    [css] 使用css3画一个扇形 四个半圆叠加,过半调整 z-index .container { width: 200px; height: 200px; position: relative; ...

  6. [css] 用css3画出一个立体魔方

    [css] 用css3画出一个立体魔方 <!DOCTYPE html> <html> <head><meta charset="utf-8" ...

  7. h5画三角形_如何利用css或html5画出一个三角形?两种不同的制作三角形方法(代码实例)...

    我们在平时的前端开发的时候,有时候是需要一些小图形来丰富一下页面效果,比如:下拉列表的倒三角图形.那么这样的一个三角形是如何制作出来的,本章给大家介绍如何利用css或html画出一个三角形?两种不同的 ...

  8. 运用html画一个三角形,利用css或html5画出一个三角形的方法

    利用css或html5画出一个三角形的方法 发布时间:2020-09-14 14:49:22 来源:亿速云 阅读:83 作者:小新 这篇文章主要介绍利用css或html5画出一个三角形的方法,文中介绍 ...

  9. svg css实现霓虹灯

    svg css文字霓虹灯 事情是酱紫的,因为两会马上来了,公司产品要搞免费试用活动.首页要求醒目抓眼,UI小姐姐废了九牛九虎之力让产品同意了一版霓虹灯效果图,要在首页中的部分文字大量使用霓虹效果.UI ...

最新文章

  1. 判断某数组是不是二叉树的后序遍历序列 python递归与非递归解法
  2. Android 自定义Dialog背景透明及显示位置设置
  3. boost::log模块实现宽字符日志记录示例
  4. 面试:MySQL InnoDB 事务隔离
  5. MySQL 常用分库分表方案,都在这里了!
  6. 为什么谈设计总爱提老庄之道
  7. Python小游戏及登录系统
  8. NTC与PTC压敏电阻在电源电路中起的作用
  9. 为你的企业建立竞争情报系统
  10. php话费充值,手机话费充值接口
  11. 青岛阳光计算机学校,青岛恒星科技学院
  12. 基于数据驱动的故障检测(一)
  13. Python 游戏开发: 外星人入侵
  14. 学习《华为基本法》(5):经营重心
  15. Vue突然报错 doesn‘t work properly without JavaScript enabled
  16. one world,one dream
  17. 欺骗的艺术----(9)
  18. GRE Issue 分类题库及翻译
  19. “澳本聪”是怎么从网红一步步变成“众矢之的”?
  20. Hadoop、Yarn相关命令简介

热门文章

  1. itext实现图片等比缩小放大转pdf
  2. #金专奖获奖方案展播# | 移动端云机魔测平台
  3. PLSQL Developer备份恢复oracle数据
  4. 分享几个特别特别强的资源福利网站
  5. 创建react脚手架
  6. nvm下载node时没有npm
  7. 更改计算机硬盘,教您win7硬盘盘符怎么更改
  8. 抖音视频播放量低、没推荐,原来是这样来的?
  9. 【java-枚举与注解】
  10. 删除键模式转换,为啥覆盖了后面的字?