文出自:闪电矿工翻译组
原文地址:Drawing Realistic Clouds with SVG and CSS
原文作者:Beau Jackson
仓库原文链接:Drawing Realistic Clouds with SVG and CSS
译者:sichenguo
希腊神话中有这样一个故事是讲述宙斯创造出来一个云女神涅斐勒,并且类似大多数的希腊神话一样的,这个故事非常的奇异且限制级。下面一个简短克制的版本。
我们能够知道的是: 涅斐勒是由宙斯以他自己美丽的妻子的形象创造的。一个凡人遇见涅斐勒,陷入爱河,并且他们一起有了一个孩子,确切的说是一个半人半马的婴儿。
很怪诞对吧,值得庆幸的是,在浏览器中创建云的过程要简单得多,而且风险要小得多。
(Demo)
最近,我发现开发者Yuan Chuan 已经实现了用代码生成逼真的云。对我来说,浏览器中的云这个概念一直如同希腊神话中的那边神秘。
让我们来看一下这个’画笔‘吧 (点这里),可以见到的是作者通过使用 box-shadow 作为包含两个滤镜的 <filter> 元素的补充实现了这个令人惊叹的‘云图’!
想要绘制出兼顾写实和精致的云图,需要搭配使用feTurbulence 和feDisplacementMap 这两个滤镜。这两个滤镜不仅可以具有强大且复杂的功能,并且还可以提供一些令人兴奋的特性(其中包含奥斯卡获奖算法))!当然,这些功能在浏览器‘引擎盖’下有着令人生畏的复杂性。
虽然这些 SVG 滤镜的物理特性超出了本文的范围,但 MDN 和 w3.org 上提供了大量文档供学习参考。另外还有 feTurbulence 和 feDisplacement 介绍。
对于本文,我们将专注于学习使用这些 SVG 滤镜来实现令人惊奇的效果。滤镜背后的实现算法并不在我们的研究范围内,就像艺术家虽然可以绘制出美丽的景观但却不用懂得油漆的分子结构。
而我们需要做的只是密切关注一小部分 SVG 属性,这些属性使得我们可以在浏览器中绘制逼真的云图。通过学习这些属性可以让我们在项目中按照自己的意愿更好的制作出特定的滤镜效果。
CSS 规则 box-shadow的五个值得关注的属性:
box-shadow: <offsetX> <offsetY> <blurRadius> <spreadRadius> <color>;
让我们来增大这些值(可能会高于正常的开发者会做的),这样在视图的右下方就会有阴影出现。 !
(Demo)
#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; }
你肯定表演或者见过过皮影戏吧?
Credit: Double-M
类似于通过改变手的形状来改变阴影的方式,我们的 HTML 中的“源形状”可以通过移动或者变形来同步影响其在浏览器中呈现的阴影的形状。box-shadow 复制原始图形的圆角效果。SVG 滤镜对于元素都以及元素的 shadow 的都会生效。
<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>)。我们的源<div>和它的阴影都被滤波器独立地扭曲。
我们通过 ID 选择器(#cloud-circle) 将下面的 CSS 规则添加到目标元素上:
#cloud-circle { filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; }
好吧,添加上 SVG 滤镜依旧没能给我们带来什么惊喜。
(Demo)
别担心!这才仅仅只是开始,更有趣的还在后面。
使用这一属性进行的一些实验可以产生显著的效果。暂时,让我们保持它的 feTurbulence 不变,只调整 DisplacementMap 的 scale 属性。
随着 scale 的增加(每次增加 30 ),我们的源 <div> 开始扭曲变形且它的投下阴影更接近天空中云随机的形状。
<feDisplacementMap in="SourceGraphic" scale="180" />
The scale attribute incremented by values of 30. (Demo)
好的,通过改变 scale ,好像终于接近了正确云形状的的数值范围!让我们稍微改变下颜色,以便看起来更像一朵 云彩 ☁️。
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; }
现在我们的图形越来越接近真实的云效果了!
下面的一组图像显示了 blur 对 box-shadow 效果的影响。下面的图形中 blur 的数组依次递增。
The cloud becomes "softer" as the blur value increases.
为了使我们的云带有一些积云效果,可以稍微扩大 <div> 的尺寸。
#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 60px 0px #fff; }
好的,但是现在的源 div 元素正在成为障碍。
等等!我们已经扩大了源元素的尺寸,但是它现在已经开始影响我们的“云(白色阴影)”了。 很简单,只需要相距更远的地方投影遍可以解决这个遮挡问题。
而通过通过一些 CSS 定位很好地实现源元素的隐层。<body> 元素是云 div 元素的父元素,默认情况下是静态定位的。 将苏设置为就绝对定位就可以将不需要展示的 #cloud-circle 隐藏。
#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 400px 400px 60px 0px #fff; /* Increase shadow offset */ position: absolute; /* Take the parent out of the document flow */ top: -320px; /* Move a little down */ left: -320px; /* Move a little right */ }
很棒,这样看起来我们的云图已经初步成型了。
codepen
平摊在屏幕之上的云彩,嗯,这应该是一个对我们绘制出的云图一个很好的描述,总是感觉还缺少点什么,我们应该还可以做的会更好的!
这就是我们想要的:
Credit: 图源:pcdazero
从这张照片中云的深度,质感和丰富程度来看,有一件事是清楚的:宙斯是上过艺术学校。至少,他肯定是阅读过通用组件设计原则的,这个原则阐述了一个通用性的概念:
[...]照明偏差在深度和自然的解释中起着重要作用,并且可以由设计师以各种方式操纵......使用明暗区域之间的对比度使得外观具有景深。
这段话为我们提供了一个对云图进行优化更加真实的提示。通过将不同形状,大小和颜色的图层堆叠在一起,我们可以在参考图像制造对比度中以来渲染云图。需要的只是使用 filter 制造多个图层。
<svg width="0" height="0"> <!-- Back Layer --> <filter id="filter-back"> <feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="4" /> <feDisplacementMap in="SourceGraphic" scale="170" /> </filter> <!-- Middle Layer --> <filter id="filter-mid"> <feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" /> <feDisplacementMap in="SourceGraphic" scale="150" /> </filter> <!-- Front Layer --> <filter id="filter-front"> <feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" /> <feDisplacementMap in="SourceGraphic" scale="100" /> </filter> </svg>
再加上图层可以提供更多的角度去探索 feTurbulence 以及 实现更多的功能。 我们选择使用更加平滑的 type :fractalNoise,然后将 numOctaves 设置为 6。
<feTurbulence type="fractalNoise" baseFrequency="n" numOctaves="6" />
现在,让我们将注意力集中在 baseFrequency 属性上。以下是我们在逐渐增加 baseFrequency 值的时得到的结果 :
值取两端的值时,图形都会趋向于圆形。区别就是越小,更模糊。值越大,图形就更加显得生硬。
像 turbulence,噪音,频率和 octave 这样的词可能看起来很奇怪甚至令人困惑。但不要害怕!将滤镜的效果类比为声波实际上非常准确。我们可以将低频率(baseFrequency=0.001)等同于低噪声和低频率,更高的 (baseFrequency=0.1) 值则与更清晰的音调相对应。
我们可以看到,我们对积云效果的对应的 baseFrequency 值大概位于 0.005~0.01 范围之间。
增大 numOctaves 的值可以以极其细致的细节渲染图像。但是这需要大量计算,因此需要注意的是:更细致的渲染也可能带来的还有性能问题,所以如非必要,请将此值尽量控制在一定范围内。
The higher the value we put into numOctaves the more granular detail give to our cloud.
好消息就是,在此例中,我们的云图需要的细节并不需要使用过高的 numOctaves 值,如上图所示,numOctaves 为 4 或者 5 就可以得到不错的效果。
效果图
codepen
至于 seed 属性还可以再深入研究一下。但是,就我们的目的而言, seed 的作用可以对形状造成影响。
Perlin Noise 函数(上文提到)会使用此值作为其随机数生成器的初始值。如果不设置该属性将默认 seed为零。跟 baseFrequency 的区别就是,无论我们给出什么价值 seed,都不需要担心性能损失。
不同的 seed 值产生不同的形状
上面的 GIF 展示了不同 seed 值时的效果。需要注意的是,每朵云都是分层的复合云。(虽然我调整了每个图层的属性,但我保持各自的 seed 值分布均匀。)
Credit: Brockenhexe
在这里,仔细观察参考图像,我将 3 个‘云’层(不透明度不同)叠加到一个 div 上。通过反复试验和调整 seed 参数值,最终得到的下面这个类似于照片中云的形状的效果图。
codepen
当然,如果我们认为我们绘制的这个云彩要比宙斯创造的女神还要漂亮,肯定就是狂妄自大了。
但是,随着我们对 CSS 和 SVG 滤镜的更多的了解,我们就越有能力创造出在视觉上令人惊叹的图形,比如下面这些:
Reflecting Mist
Animated Reflecting mist
Alto-Cirrus Clouds
在这篇文章中我们沉浸在 SVG 强大功能和复杂性的海洋中,虽然 SVG 滤镜通常看起来比较复杂且难以理解。
然而就好像A Single Div project这个项目和Diana Smith's painting techniques这个例子一样,有趣的和有创意的方法总是可以得到令人惊艳的效果。
我相信很多开发者都有能力制作出一个云彩出来,但是一个可以轻松制作出云彩的工具会更受欢迎。因此我开发了一个小工具做这件事。
容提要:本文讲解的Photoshop制作闪电效果教程主要使用到风格化滤镜、等高线滤镜、云彩滤镜的综合使用.
本文我们以在Photoshop里面为一幅海报添加制作闪电效果为案例,和大家分享。先呈现海报原图和使用PS添加闪电效果之后的对比图。
ps制作闪电效果分析:
教程中我们将制作电影海报中那些强大的魔法闪电效果。制作中主要利用Photoshop里面的“云彩”“等高线”等滤镜进行制作。
PS闪电效果操作步骤:
(1)执行“文件”→“打开”命令,打开一幅电影背景图片,如图31。
(2)在“图层”面板中在新建“图层 1”并为其填充黑色,如图32。
(3)执行“滤镜”→“渲染”→“云彩”命令,为“图层1”创建云彩效果,如图33。
(4)执行“滤镜”→“风格化”→“等高线”命令,打开“等高线”对话框,为图像添加等高线滤镜效果,如图34。
(5)按Ctrl+I将图像颜色反相,然后在“通道”调板中载入选区,参数如图35。
(6)将选区反选,切换到“图层”面板,将选区内的图像删除,如图36。
(7)取消选区的浮动状态,执行“图层”→“图层样式”→“外发光”命令,打开“图层样式”对话框,为图像添加外发光效果,如图37。
(8)将“图层 1”进行复制,并将复制后的图层改名为“闪电”,然后将“图层 1”图层隐藏,如图38。
(9)按快捷键Ctrl+T执行“自由变换”命令,然后右击鼠标,在弹出的快捷菜单中选择“变形”命令,如图39。
(10)调整图像周围的控制柄,对图像进行变形,调整完毕后单击Enter键确认操作,如图40。
(11)为“闪电”图层添加图层蒙版,并使用“画笔”工具对蒙版进行编辑,如图41。
(12)在“图层”面板中复制“闪电”图层,两个图层重叠后,闪电的光亮度增强。继续使用“画笔”工具对蒙版进行编辑,减弱一些区域的外发光效果,如图42。
(13)将两个闪电图层隐藏,并将“图层1”显示,使用“矩形”选框工具,绘制选区,将选区内的图像拷贝至新图层中,如图43。
(14)调整“图层2”中图像的大小、位置和旋转角度,完毕后将其复制,如图44。
(15)将“图层 1”隐藏,参照以上方法,多次复制“图层2”中的图像,并调整大小、位置和旋转角度,效果如下图45。
(16)将两个闪电图层显示,使用画笔工具,设置圆形笔触在任何一个图层2上绘制,即可添加光斑效果,至此完成本实例的制作,如图46。
本文的ps制作闪电效果案例教程就到此结束。如果你想和我一样当一个懒人,当然你也可以使用一些现成的闪电效果外挂插件来制作,请看教程:www.ittribalwo.com/article/2347.html
Photoshop风格化滤镜小结:
我们本系列的Photoshop风格化滤镜一共制作了三个案例,分别使用了查找边缘、浮雕效果和等高线等几个滤镜,让我们对风格化滤镜有了一个比较全面的认识,学到更多的知识。比如:“查找边缘”滤镜用于标识图像中有明显过渡的区域并强调边缘; "等高线"滤镜在白色背景上用深色线条勾画图像的边缘,对于在图像周围创建边框非常有用;“浮雕”滤镜则是通过将图像颜色转换为灰色,并用原图像的各处轮廓色描画边缘,从而使图像显得凸起或压低。
击右上方红色按钮关注“web秀”,让你真正秀起来
好雨知时节,当春乃发生。 随风潜入夜,润物细无声。
春节已经过去,新的一年刚刚开始,小伙伴们,今年你的目标是什么?定个小目标,挣它一个亿?分享一下我的目标,是让大家的web前端能力,更上一层楼。
下面进入主题,看下图:
CSS3线性渐变、阴影、缩放实现动画下雨效果
这个动画效果,如果让你来做,你会选择什么方式?相信很多小伙伴都会用gif图片。其实用css实现也很简单。
如果文章中有不懂的知识点,请点击文章最下方,推荐文章哦
很明显这个动画效果,是上中下结构,所以我们分3部分实现。
1、云:由多个圆拼接而成,并且有上下浮动的动画效果
2、雨滴:多个,从上而下的动画效果
3、阴影:椭圆,缩放动画效果
下面我们按步骤实现
用box-shadow制作多个圆,完成拼接,行程完整的云朵。animation,添加动画,上下浮动。
语法:box-shadow: h-shadow v-shadow blur spread color inset;
注:box-shadow,向框内添加一个或多个阴影。该属性是由逗号分隔的阴影列表,每个阴影由 2-4 个长度值、可选的颜色值以及可选的 inset 关键词来规定。省略长度的值是 0。
CSS3线性渐变、阴影、缩放实现动画下雨效果
相关推荐CSS3 box-shadow实现背景动画
.rainy { position: absolute; top: 30%; left: 50%; } .rainy:before { content: ""; color: #333; position: absolute; height: 50px; width: 50px; top: 30px; left: -40px; background: #CCC; transform: translate(-50%, -50%); border-radius: 50%; box-shadow: #CCC 65px -15px 0 -5px, #CCC 25px -25px, #CCC 30px 10px, #CCC 60px 15px 0 -10px, #CCC 85px 5px 0 -5px; animation: cloudy 5s ease-in-out infinite; } @keyframes cloudy { 50% { transform: translate(-50%, -70%); } 100% { transform: translate(-50%, -50%); } }
CSS3线性渐变、阴影、缩放实现动画下雨效果
雨滴和云一样,都是用box-shadow来实现,但是雨滴的实现要复杂的多,雨滴数量多,每个雨滴位置的改变。
.rainy { position: absolute; width: 3px; height: 6px; top: 30%; left: 50%; animation: rainy_rain .7s infinite linear; } .rainy:before { ... } @keyframes cloudy { ... } @keyframes rainy_rain { 0% { box-shadow: rgba(0, 0, 0, 0) -10px 30px, rgba(0, 0, 0, 0) 40px 40px, rgba(0, 0, 0, .3) -50px 75px, rgba(0, 0, 0, .3) 55px 50px, rgba(0, 0, 0, .3) -18px 100px, rgba(0, 0, 0, .3) 12px 95px, rgba(0, 0, 0, .3) -31px 45px, rgba(0, 0, 0, .3) 30px 35px; } 25% { box-shadow: rgba(0, 0, 0, .3) -10px 45px, rgba(0, 0, 0, .3) 40px 60px, rgba(0, 0, 0, .3) -50px 90px, rgba(0, 0, 0, .3) 55px 65px, rgba(0, 0, 0, 0) -18px 120px, rgba(0, 0, 0, 0) 12px 120px, rgba(0, 0, 0, .3) -31px 70px, rgba(0, 0, 0, .3) 30px 60px; } 26% { box-shadow: rgba(0, 0, 0, .3) -10px 45px, rgba(0, 0, 0, .3) 40px 60px, rgba(0, 0, 0, .3) -50px 90px, rgba(0, 0, 0, .3) 55px 65px, rgba(0, 0, 0, 0) -18px 40px, rgba(0, 0, 0, 0) 12px 20px, rgba(0, 0, 0, .3) -31px 70px, rgba(0, 0, 0, .3) 30px 60px; } 50% { box-shadow: rgba(0, 0, 0, .3) -10px 70px, rgba(0, 0, 0, .3) 40px 80px, rgba(0, 0, 0, 0) -50px 100px, rgba(0, 0, 0, .3) 55px 80px, rgba(0, 0, 0, .3) -18px 60px, rgba(0, 0, 0, .3) 12px 45px, rgba(0, 0, 0, .3) -31px 95px, rgba(0, 0, 0, .3) 30px 85px; } 51% { box-shadow: rgba(0, 0, 0, .3) -10px 70px, rgba(0, 0, 0, .3) 40px 80px, rgba(0, 0, 0, 0) -50px 45px, rgba(0, 0, 0, .3) 55px 80px, rgba(0, 0, 0, .3) -18px 60px, rgba(0, 0, 0, .3) 12px 45px, rgba(0, 0, 0, .3) -31px 95px, rgba(0, 0, 0, .3) 30px 85px; } 75% { box-shadow: rgba(0, 0, 0, .3) -10px 95px, rgba(0, 0, 0, .3) 40px 100px, rgba(0, 0, 0, .3) -50px 60px, rgba(0, 0, 0, 0) 55px 95px, rgba(0, 0, 0, .3) -18px 80px, rgba(0, 0, 0, .3) 12px 70px, rgba(0, 0, 0, 0) -31px 120px, rgba(0, 0, 0, 0) 30px 110px; } 76% { box-shadow: rgba(0, 0, 0, .3) -10px 95px, rgba(0, 0, 0, .3) 40px 100px, rgba(0, 0, 0, .3) -50px 60px, rgba(0, 0, 0, 0) 55px 35px, rgba(0, 0, 0, .3) -18px 80px, rgba(0, 0, 0, .3) 12px 70px, rgba(0, 0, 0, 0) -31px 25px, rgba(0, 0, 0, 0) 30px 15px; } 100% { box-shadow: rgba(0, 0, 0, 0) -10px 120px, rgba(0, 0, 0, 0) 40px 120px, rgba(0, 0, 0, .3) -50px 75px, rgba(0, 0, 0, .3) 55px 50px, rgba(0, 0, 0, .3) -18px 100px, rgba(0, 0, 0, .3) 12px 95px, rgba(0, 0, 0, .3) -31px 45px, rgba(0, 0, 0, .3) 30px 35px; } }
CSS3线性渐变、阴影、缩放实现动画下雨效果
阴影实现是最简单的啦,加上缩放,透明度改变就可以了,当然要和上面的云配合起来,云上,阴影变小,云下,阴影变大。
.rainy:after { content: ""; position: absolute; top: 120px; left: 50%; height: 15px; width: 120px; background: rgba(0, 0, 0, .5); border-radius: 50%; transform: translate(-50%, -50%); animation: cloudy_shadow 5s ease-in-out infinite; } @keyframes cloudy_shadow { 50% { transform: translate(-50%, -50%) scale(0.8); background: rgba(0, 0, 0, .2); } 100% { transform: translate(-50%, -50%) scale(1); background: rgba(0, 0, 0, .5); } }
演示地址:http://demo.javanx.cn/raindrop/index2.html
CSS3 box-shadow实现背景动画
从浅到深的学习 CSS3阴影(box-shadow)
CSS3最容易混淆属性transition transform animation translate
喜欢小编的点击关注,了解更多知识!
源码地址和源文件下载请点击下方“了解更多”
*请认真填写需求信息,我们会在24小时内与您取得联系。