实验:JS+定时器实现随机飘雪特效
作者:reader1   类别:Python开发    日期:2018-10-29 17:32:16    阅读:629 次   消耗积分:0 分




项目介绍



随机飘雪的网页特效我们经常在一些文艺类网站或博客中看到,再配合背景音乐可以更好地营造温馨的氛围。我们先来看看最终运行效果如图所示。


图片11.png 

 

我们先来说明一下该项目要实现的功能主要包含哪些方面:

(1) 通过代码来新增一片或多片雪花。

(2) 雪花新增的位置是随机的。

(3) 可以随时开始和暂停雪花的移动。

(4) 可以删除所有或部分雪花。

(5) 雪花往下移动的过程中还需要随时补充雪花,这样才能模拟下雪的效果。

(6) 当雪花移出整个屏幕区域后,不应该继续保留该雪花,应该及时将其删除,否则会浪费浏览器的处理资源。

(7) 背景音乐的播放。

(8) 开始按钮和停止按钮应该交替使用,不能多次点击。




开发思路


首先,本项目演练所涉及到的知识点虽然逻辑不算复杂,但是面还是比较方的,CSS样式,DOM操作,BOM操作,定时器使用,雪花控制的细节等一应俱全,所以是一个值得大家去认真完成的项目。

基于对以上8个功能点的梳理,我们来看看其核心实现思路:


1.新增雪花

新增一片雪花的操作其实跟新增一个普通HTML元素没有任何本质区别,我们可以通过两种方式来完成。第一种方式是直接通过document.write()方法往页面中输出一个<img>标签,并设置好相应的属性即可。但是这种方式有一个问题,就是当我们往页面中输出内容的时候,页面中的之前存在的元素将会被覆盖,所以这并不是一种良好的解决方案。那么,我们自然会使用到第二种解决方案:通过调用document.createElement()的方法来向任意容器中增加元素,并对该元素设置CSS属性的方式完成元素的增加。在前面章节中,我们在讲解DOM元素的新增的知识点时专门为大家做过演示,所以自然我们会选择这一标准的做法。

但是此处需要注意的是,我们新增的是一片雪花,而不是简单的一个普通元素,而且还得让该雪花能够移动起来。所以从细节上来说,我们必须先新增一个DIV,并设置相应的属性。同时在该DIV中,我们还得增加一张图片,同时为了保证雪花的真实效果和美观度,该雪花图片必须使用一张透明背景的图片,所以图片必须是PNG格式的。

 

2.位置随机。

要实现一片随机位置的雪花,那么必然我们需要考虑两个核心因素:一是必须使用固定定位,这样才可以实现位置的强制调整;二是必须考虑浏览器窗口的高度和宽度,因为如果让雪花飘在窗口之外没有任何意义。

那么先来看看关于定位的问题,既然我们是将一片雪花放在一个DIV当中,所以我们只需要对该DIV设置“position: fixed”即可。进而再对其通过设置其lefttop属性进行定位。

另外,关于如何取得浏览器窗口的宽度和高度的问题,在介绍BOM的操作一节,我们为大家提到过,使用window.innerWidthwindow.innerHeight即可取得,所以技术上不存在任何难点。关键点在于,取得窗口的最大宽度和高度后,我们还需要基于该数值来生成两个随机数,一个是横向的数值,用于设置雪花的left属性;一个是纵向的数值,用于设置雪花的top属性。这样,一个随机位置的雪花即完成。

 

3.开始和暂停。

当开始让雪花移动时,我们当然需要使用setInterval()定时器来实现该功能。定时器本身就像一个死循环的结构一样,在定时器任务代码中,每触发一次定时器,我们就让所有雪花的top属性基于该片雪花现有的位置再增加几个随机的像素值,这样就可以实现快慢不一的雪花飞舞的效果。

当然,还得注意一点的是,定时器的时间间隔设为多久,雪花往下移动的单次距离在多少像素的范围内,能够让雪花飞舞的过程看上去更加自然,这是需要我们实现运行代码的过程中进行调试,找到一个最佳效果。其基本原则是在尽可能短的时间内移动的距离也尽可能短,这样可以让飞舞的效果更加平滑。

 

4.删除雪花。

要实现雪花的删除功能,我们首先必须要获取到某片雪花对应的元素,然后调用其方法:remove()即可实现删除。我们可以一次性删除所有的雪花,也可以实现一次性删除部分雪花,这个看我们自己的需要。本项目演练主要为大家提供一个可选的功能而已。

 

5.补充新的雪花。

由于雪花会一直往下移动,最终会消失在浏览器窗口中,所以为了保持雪花一直在下的效果,我们还必须在此过程中不停地自动增加雪花。要实现这一效果,方法有很多,但是其核心目的是,当触发到某个条件时,我们就应该考虑让雪花新增。比如当某片雪花距离浏览器顶部的距离(即元素的标准属性:offsetTop)超过了浏览器窗口的高度(即雪花已经消失在浏览器窗口的可视范围时),我们就应该新增一片雪花补上。也或者是在雪花移动到某个中间位置时,我们就触发新增的操作,进而实现雪一直下的效果。

 

6.移出无效雪花。

这是一个比较简单的实现方法,只需要在计时器代码中对所有雪花的位置进行一下判断,当其offsetTop属性对应的值超过浏览器窗口的高度时即可将该片雪花移除。当然,每当我们移出一片雪花时,我们就应该继续再新增一版雪花补上。

 

7.背景音乐。

背景音乐的使用可以直接使用HTML5自带的<audio>标签实现即可,并且设置该音频为自动加载,自动播放,也不需要在界面上显示控制条。

 

8.开始停止按钮交替点击。

首先我们需要明白,为什么开始按钮不能连续点击。因为我们会使用到定时器对象,而每当我们点击一次,就会生成一个新的定时器对象,如果不停地点击,就会生成很多定时器对象,这样会导致每个定时器对象就会去移动雪花,造成的结果就是雪花移动越来越快。

同样,不停地点击停止按钮将毫无意义。所以将二者进行一下结合,比较好的解决方案就是当页面加载时,让“停止”按钮变成不可用,启用“开始”按钮。当点击“开始”后,“开始”按钮马上变灰,而“停止”按钮可用。同样的,当点击“停止”按钮后,将“停止”按钮变灰,而“开始”按钮变成可用。具体的实现只需要通过设置按钮的disabled属性即可。


代码实现


通过对上述开发思路的梳理和分解,相信我们现在的脑海里已经对实现该功能有一个大致的轮廓了。但是咱们不急于一口气做完,一步一步地来实现上述功能的代码。

 

1. 完成页面的基本布局和样式设置,同时添加背景音乐,代码如下:

<!DOCTYPE html>
<
html>
<
head>
    <
meta charset="UTF-8">
    <
title>随机飘雪</title>
    <
style>
        
body {
            
background-imageurl("../image/snow-night.jpg");

/* 此处请大家自行在网上挑选一张喜欢的背景图片即可 */
            
background-sizecover;   /* 让背景图自适应浏览器窗口大小 */
        }
        
input {
            
width: 80px;
            
height: 30px;
            
font-weightbold;
        }
    </
style>
</
head>
<
body>

<audio preload="auto" loop="loop" autoplay>

<source src="backmusic.mp3" type="audio/mpeg"></audio>
<
input type="button" value="新增" style="background-color#ff7e61;/>
<
input type="button" value="开始" style="background-color#8aff95;"

id="startButton" />
<
input type="button" value="停止" style="background-color#FC5753;"

id="stopButton" />
<
input type="button" value="删除" style="background-color#79d1ff;/>
</
body>
</
html>

 

2. 完成基本布局后,我们来实现雪花的新增效果,并响应“新增”按钮的单击事件,核心代码如下:

// 新增一片雪花
function createOneSnow() {
    
var leftX = Math.random() * window.innerWidth;
    
var topY = Math.random() * window.innerHeight;
    
var snowDiv = document.createElement("div");
    snowDiv.
style.position "fixed";
    snowDiv.
style.left = leftX + "px";
    snowDiv.
style.top = topY + "px";
    
// 为该新增的DIV元素内部添加一张雪花的图片
    snowDiv.innerHTML "<img src='../image/white-snow.png' width='20' />";
    
// 将该DIV元素增加到BODY中,浏览器才会对其进行渲染
    document.body.appendChild(snowDiv);
}

// 新增一批雪花
function createManySnow() {
    
for (var i = 1; i <= 20; i++) {
        
createOneSnow();
    }
}

 

此处为大家提供了两个创建雪花的方案,当然其核心都是新增一片雪花。新增一片雪花的函数createOneSnow()同时也是为了在我们补充雪花时调用。而新增一批雪花的函数createManySnow()的主要目的则是为了响应“新增”按钮而设置的,这样我们在使用时可以一次性增加多片,省去频繁的点击操作。

 

3. 开始让雪花飞舞,并且对何时删除雪花,何时新增雪花设定策略,代码如下:

// 开始让雪花移动,用定时器调用该函数

function startFly() {
    
var allSnows = document.getElementsByTagName("div");
    
for (var i=0; i<allSnows.length; i++) {
        
var randomTop = Math.random() * 6;  // 每次移动的距离在6个像素以内
        allSnows[i].style.top = allSnows[i].offsetTop + randomTop + "px";
        
// 当某个雪花的位置正好可以被200整除时,新增一片雪花
        if (allSnows[i].offsetTop % 200 == 0) {
            
createOneSnow();
        }
        
// 当某个雪花的位置已经超出浏览器窗口时,将该雪花删除,并再新增一片
        if (allSnows[i].offsetTop window.innerHeight) {
            allSnows[i].remove();
            
createOneSnow();
        }
    }
    
// 开始按钮变成不可用,让停止按钮可用
    document.getElementById("startButton").disabled "disabled";
    
document.getElementById("stopButton").disabled "";
}

 

4. 最后,我们来实现“停止”和“删除”两个按钮的事件代码:

版权所有,转载本站文章请注明出处:蜗牛笔记, http://www.woniunote.com/article/73
上一篇:实验:JS函数应用与TDD测试驱动开发
下一篇:实验:JS+定时器实现图片轮播
${comment['nickname']}   ${comment['createtime']}
  
       
${comment.content}
${reply.nickname} 回复 ${comment.nickname}    ${reply.createtime}
     
  
回复内容:${reply.content}