简单的下雪效果实现

HomeDevelopment简单的下雪效果实现

2013 年元旦,杭州下起了小雪。今日起来,发现到处都是白花花的一片,天空中也还飘着雪。一时间兴起,找了网页上雪花的实现效果,发现很赞。

2013 年元旦,杭州下起了小雪。今日起来,发现到处都是白花花的一片,天空中也还飘着雪。一时间兴起,找了网页上雪花的实现效果,发现很赞。

在一番 Google 之后,发现有一些下雪效果挺不错的。这里做下简单的实现方法介绍:

飘雪页面的 HTML

为了添加雪花和雪球,我们需要一个节点,从而在这里面动态创建雪花节点,定义一个Idsnowglobe

<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轴,并从数组中销毁,再创建一个新的雪花。

参考文章

  • 作者「」于 更新本文
  • 文章声明:自由转载-非商用-非衍生-保持署名 | BY-NC-SA
← CSS3 图片滤镜 使用 Peaches 合并背景图片→
  • 获取每日の能量源
  • ATP