华灯初上,窗外的雨淅淅沥沥飘打在窗户的玻璃之上。站在室内的你,望着雨中的夜色,是不是让你增添几分惆帐。似乎如此的场景只有在诗中才会出现。那么今天我们一起来用CSS技术来描绘这样的一个场景。
这里仅是用CSS技术来演示这样的一个场景,可能并不太实用。然而这是一个探索CSS新功能的最佳机会。可以让你尝试使用一些新特性和新工具。并且逐渐将在工作中实践。在制作窗口雨滴效果,将使用到 HAML 和 Sass 。
看到上面的效果是不是有点像人站室内看窗外雨中的夜景,窗户上雨滴的效果是那么的真实,窗外的夜景却又是那么的模糊。咱们不在诗意化了,我想大家更为关注的是用什么样的技术来实现这样的一个效果。
在这个示例中,使用了 HAML 和 Sass 来替代我们熟悉的HTML和CSS。主要是为了制作雨滴需要上百个 <div>
元素,另外需要对上百个 <div>
写样式,毕竟每个雨滴都长得不一致嘛。使用预处理器除了可以帮助我们减少工作量之外,还可以使用预处理器中的循环、变量等。最主要的是可以使用随机函数产生的随机值,让我们不需要单独处理上百个雨滴。
有关于 HAML 和 Sass 的语法可以各自到其官网上查阅。如果你自己本地电脑不具备这样的开发环境,可以直接在 Codepen 创建DEMO,并且选择对应的预处理器。在HTML和CSS的配置中选择对应的预处理器。比如在HTML设置中选择HAML,在CSS设置中选择SCSS。
有关于Sass更多的中文教程,可以点击这里阅读。
制作窗户雨滴的效果,其结构并不太复杂。主要分两个层次,其中是窗户,而另个是雨滴。在案例中使用 .window
来表示窗户,在 .raindrops
容器中放置了上面个雨滴.雨滴是通过 .border
和 .drops
来制作。并且将窗户 .window
和雨滴 .raindrops
都放置在容器 .container
中:
.container .window .raindrops .borders + (1..120).each do .border .drops + (1..120).each do .raindrop
编译出来的结构:
<div class="container"> <div class="window"></div> <div class="raindrops"> <div class="borders"> <div class="border"></div> <!-- 此处省略 118个border --> <div class="border"></div> </div> <div class="drops"> <div class="raindrop"></div> <!-- 此处省略 118个raindrop --> <div class="raindrop"></div> </div> </div> </div>
样式分为三个层次:
接下来简单了解这些效果是怎么实现的,又使用了哪些CSS新特性。
整个效果都是使用Sass来编写,如果你从未了解或接触过Sass,建议您先对其做一个简单的了解。这样更有助于你快速理解案例效果制作。
窗外的夜景找了一张华灯初上的图片,而且让窗户占据全屏,在这里首先声明三个变量:
$image: "http://www.w3cplus.com/sites/default/files/blogs/2015/1506/huadenchushang.jpg"; $width:100vw; $height:100vh;
初此之外,需要设置雨滴变量:
$raindrops:120;
特别需要注意,雨滴的变量值最好和HTML中的雨滴结构相匹配。
首先要做的是让窗户占据全屏。其实就是让 .window
全屏显示。至于如何实现全屏效果,这也不是什么难的事情。我想懂点CSS的同学,分分钟就能搞定。不过这里采用的是CSS3的新方法,采用viewport单位来实现全屏效果:
.container{ position:relative; width:$width; height:$height; overflow:hidden; } .window{ position:absolute; width:$width; height:$height; background:url($image); background-size:cover; background-position:50%; }
使用了两个关键知识点:
vw
和 vh
,让容器 .container
和 .window
和视窗窗口一样大。(有关于Viewport单位相关介绍,这里有做详细介绍) background-size
属性,让背景图片满屏显示。 我们要的效果不仅仅是背景图全屏这么简单,看上去图片是模糊的效果。或许有同学会说,使用制作软件整一张模糊的背影图片,也就分分钟的事情。如果你还是使用这样的方法来处理,说明你已经Out了。
CSS3中有一个 filter
属性 ,将其设置 blur()
,效果就出来了。
.window{ ... filter:blur(10px); }
在我们继续讨论之前,让我们看看现实生活中雨滴在窗户上的效果:
图片来自: Wikipedia
由于折射,雨滴翻转图像。另外,雨滴形状或多或少有些类似半球体,而且综们看起来有黑色边框。
基于我们看到的雨滴效果,让我们来尝试制作一个单独的雨滴效果。
.container .window .raindrop
$drop-width:15px; $drop-stretch:1.1; $drop-height:$drop-width*$drop-stretch; .raindrop{ position:absolute; top:$height/2; left:$width/2; width:$drop-width; height:$drop-height; border-radius:100%; background-image:url($image); background-size:$width*0.05 $height*0.05; transform:rotate(180deg); }
这是很简单的,我做就是使用 div.raindrop
画了一个椭圆。并且用了当初的背景图进行了填补,并做了一个倒转的效果。
现在,我们要添加一个小边框,让雨滴看起来更像雨点(看起来有立体效果)。
.container .window .border .raindrop
.border{ position:absolute; top:$height/2; left:$width/2; margin-left:2px; margin-top:1px; width:$drop-width - 4; height:$drop-height; border-radius:100%; box-shadow:0 0 0 2px rgba(0,0,0,0.6); }
请注意,我们不只是添加了一个边框,我们还对边框进行了挤压,所以看起来雨滴更自然一些。
雨滴看上去OK了,这个时候我们可以添加数以百计的雨滴:
.container .window .raindrops .borders + (1..120).each do .border .drops + (1..120).each do .raindrop
我们做了 120
个雨滴。
接下来使用Sass的循环给每个雨滴写样式:
@for $i from 1 through $raindrops{ $x:random(); $y:random(); $drop-width:5px+random(11); $drop-stretch:0.7+(random()*0.5); $drop-height:$drop-width*$drop-stretch; .raindrop:nth-child(#{$i}){ left:$x * $width; top:$y * $height; width:$drop-width; height:$drop-height; background-position:percentage($x) percentage($y); } .border:nth-child(#{$i}){ left:$x * $width; top:$y * $height; width:$drop-width - 4; height:$drop-height; } }
这里采用了Sass的 @for
循环对每个雨滴做样式处理,并且使用随机函数 random()
产生随机值,让每个雨滴的大小,挤压都不一致。同时还使用 percentage()
函数,让雨滴的背景图采用不同的位置。
上面看到的效果都是静态的,为了让它更具下雨的效果。雨滴滴下的效果,可以使用CSS3的 animation
来制作动画效果。
@keyframes falling { from { } to { transform: translateY(500px); } }
定义好 falling
动画之后,只需要在雨滴上调用:
@for $i from 1 through $raindrops{ $x:random(); $y:random(); $drop-width:5px+random(11); $drop-stretch:0.7+(random()*0.5); $drop-delay: (random()*2.5) + 1; $drop-height:$drop-width*$drop-stretch; .raindrop:nth-child(#{$i}){ left:$x * $width; top:$y * $height; width:$drop-width; height:$drop-height; background-position:percentage($x) percentage($y); animation: #{$drop-delay}s falling 0.3s ease-in infinite; } .border:nth-child(#{$i}){ left:$x * $width; top:$y * $height; width:$drop-width - 4; height:$drop-height; animation: #{$drop-delay}s falling 0.3s ease-in infinite; } }
到了这一步,你也就能看到文章开头显示的雨滴窗户的效果了。是不是感觉很爽呀。
文章一步一步演示了如何使用CSS新特性制作一个华灯初上,雨滴窗户的效果。整个实现过程采用了预处理器来编写代码。从整个过程中你可以很明显的感知,如果没有HAML和Sass这样的预处理器,你要为数以百计的雨滴写样式效果,那绝对是一件非常苦逼的事情。而使用之后,采用他们的功能特性,配合CSS3的一些新特性就能很轻松的完成。
浏览这个效果建议您使用Chrome浏览器浏览,因为这里使用了CSS3一些新特性,大家应该都懂的。千万别问我IE6浏览器怎么破,我也破不了。
如果您有更好的思路或建议,欢迎在下面的评论中留言。
特别声明,雨滴窗户的效果思路来自于 @Lucas Bebber 写的博文《 CSS-Only Raindrops on Window Effect 》。如果需要转载,烦请注明英文出处: http://blogs.adobe.com/dreamweaver/2015/06/css-only-raindrops-on-window-effect.html
常用昵称“大漠”,W3CPlus, Sass中国 创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。