2013 年元旦,杭州下起了小雪。今日起来,发现到处都是白花花的一片,天空中也还飘着雪。一时间兴起,找了网页上雪花的实现效果,发现很赞。
在一番 Google 之后,发现有一些下雪效果挺不错的。这里做下简单的实现方法介绍:
飘雪页面的 HTML
为了添加雪花和雪球,我们需要一个节点,从而在这里面动态创建雪花节点,定义一个Id
为snowglobe
:
<div id="snowglobe"> </div>
雪花的 CSS 样式
有了节点之后,还需要定义好页面的样式。我们需要一个重置浏览器属性的样式、雪花样式,具体的写法如下:
重置浏览器样式(这是一个简单的重置样式)
html, body { margin: 0; padding: 0; width: 100%; height: 100%; } body { background: #a2cade; }
设置雪花窗口的样式
#snowglobe { width: 100%; height: 100%; position: relative; //必须的这个 top: 0; left: 0; overflow: hidden; }
设置雪花样式
#snowglobe .flake { position: absolute; //绝对定位,这样雪花就可以通过 top,left,right 等属性设置位置了 width: 1px; height: 1px; color: rgba(255,255,255,0); //雪花的颜色 text-shadow: 0 0 3px rgba(255,255,255,1); }
为雪花添加 Javascript,让雪花飘起来
现在,我们将所有这些结合在一起,制造雪花和雪花动画效果了。这时候,我们需要通过 Javascript 来实现。
首先,我们需要一些脚本函数来获取浏览器窗口的大小,并再我们指定的范围内得到一个随机数(这个随机数是为了制造雪花乱飘的效果)。
//获取宽度 function getWidth() { var x = 0; if (self.innerHeight) { x = self.innerWidth; } else if (document.documentElement && document.documentElement.clientHeight) { x = document.documentElement.clientWidth; } else if (document.body) { x = document.body.clientWidth; } return x; } //获取高度 function getHeight() { var y = 0; if (self.innerHeight) { y = self.innerHeight; } else if (document.documentElement && document.documentElement.clientHeight) { y = document.documentElement.clientHeight; } else if (document.body) { y = document.body.clientHeight; } return y; } //获取随机数函数 function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
接下来,让我们设置一些变量。
var width = getWidth(); var height = getHeight(); var flakeCount = 50; //雪花的数量 var gravity = 0.7; //重力值 var windSpeed = 20; //风速 var flakes = []; //空数组,用来跟踪雪花
接下来,我们需要添加我们的雪花,并且跟踪已经添加露多少片。
var currentFlake = 0; var snowglobe = document.getElementById("snowglobe");
现在,我们可以使用一个循环,当前数量少于 flakeCount 的时候,就可以执行。这个循环里面要做的事情如下:
- 创建一个雪花节点
•
- 为这个节点设置好字体大小,位置,速度(这些都是随机的)
- 再循环制造雪花,并添加到飘雪窗口 snowglobe
while (currentFlake < flakeCount) { var flake = document.createElement("div"); flake.className = 'flake'; flake.style.fontSize = getRandom(12, 24) + 'px'; flake.style.top = getRandom(0, height) + 'px'; flake.style.left = getRandom(0, width) + 'px'; flake.innerHTML = "•"; newFlake = snowglobe.appendChild(flake); newFlake.speed = getRandom(1, 100); flakes.push(newFlake); currentFlake++; }
好啦,初始化的时候,这些静态的雪花就会定在页面里。我们还需要遍历之前定义好的数组,来完成飘雪的效果。先搞定飘雪的动画函数吧,简单的思路如下:
- 对于每一个雪花,它会计算一个新的Y轴位置,算法是:高度+单个速度*重力
- 如果雪花在屏幕底部,我们将对其重置,将其略高于屏幕,从上再飘下来
- 如果雪花没有X轴位置,则获取当前位置,加上Y轴的位置除以风速取正弦值
- 如果雪花在左侧或者右侧,重新往左、右偏移
- 最后,把重置好的位置更新
function doAnimation() { for (var i = 0; i < flakes.length; i++) { newX = false; newY = false; // 计算 Y轴的位置 newY = parseFloat(flakes[i].style.top) + (flakes[i].speed / 100) * gravity; if (newY > height) { newY = 0 - parseInt(flakes[i].style.fontSize); // 如果在最低端,则随机 X轴 newX = getRandom(0, width); } // 如果 X轴的位置没有随机,那也计算出来 if (!newX) newX = parseFloat(flakes[i].style.left) + Math.sin(newY / windSpeed); if (newX < -20) newX = width + 20; if (newX > width + 20) newX = -20; // 重置新的位置 flakes[i].style.top = newY + 'px'; flakes[i].style.left = newX + 'px'; } }
现在,我们需要将飘雪功能运行在一个固定时间间隔里。我们使用一个计时器:setInterval(doAnimation, 10);
Ok,大概的飘雪功能已经完成。还有最后一个需要处理的,就是浏览器的重置,拉升或者缩小浏览器时,更新了窗口,所以需要做下监听:
window.onresize = function(event) { width = getWidth(); height = getHeight(); }
飘雪效果的一些扩展
更多的雪花样式
完成这个飘雪效果还是挺简单的,但是这里的雪花还是比较单一。我们可以扩展一下雪花的样式,具体的思路是:
- 添加样式,可以是flake1, flake2, flake3…
- 通过 Javascript 创建雪花节点的时候,也通过随机数创建 className
- 这里的雪花可以定义好宽度、高度,背景图片。
积雪效果怎么做
有一个思路,就是在更新雪花位置的时候,当雪花 Y轴在底部位置时,记录下该节点,锁住 X轴和 Y轴,并从数组中销毁,再创建一个新的雪花。