Javascript之实现页面倒计时效果

本文将从需求实现的角度,逐步讲解如何在页面上实现倒计时效果,其中部分涉及到的知识会做拓展讲解,最后将所有代码封装,适用于不同情况下倒计时功能的实现。


效果图

倒计时效果图


一、分析需求

要实现倒计时效果,可拆解为以下三个部分进而逐个击破:

1、 使用Date方法计算对应倒计时的数据并返回
2、 利用DOM操作将得到的数据渲染到页面中
3、 通过JavaScript原生API(setInterval或setTimeout)实现倒计时效果


二、代码实现

1、 使用Date方法计算对应倒计时的数据并返回

类型1:传入具体时间对象,如2020/12/31 到 当前时间 的倒计时

function countDown(){
	// 创建目标时间对象
    var target_time = new Date("2020/12/31");
    // 计算目标时间对象到当前时间的毫秒数
    var reduce_ms = target_time.getTime() - Date.now(); 
    // 返回需要的数据
    return {
        day  : parseInt(reduce_ms / 1000 / 3600 / 24),
        hour : parseInt(reduce_ms / 1000 / 3600 % 24),
        min  : parseInt(reduce_ms / 1000 / 60 % 60 ),
        sec  : Math.round(reduce_ms / 1000 % 60)
    }
}

类型2:传入需要倒计时的具体时间,如5小时倒计时

function countDown(){
    var target_time = new Date();
    // 获取当前时间5小时后的目标时间对象
    target_time.setHours(target_time.getHours() + 5);
    // 计算目标时间对象到当前时间的毫秒数
    var reduce_ms = target_time.getTime() - Date.now(); 
    // 返回需要的数据
    return {
        day  : parseInt(reduce_ms / 1000 / 3600 / 24),
        hour : parseInt(reduce_ms / 1000 / 3600 % 24),
        min  : parseInt(reduce_ms / 1000 / 60 % 60 ),
        sec  : Math.round(reduce_ms / 1000 % 60)
    }
}

问:为何要以对象的形式返回数据?
答:便于后续提取需要的数据渲染到页面中

2、 利用DOM操作将得到的数据渲染到页面中

步骤1:向HTML写入对应节点,此操作可通过 innerHTML 实现
* 为方便理解本文直接手动写入

<p>
    倒计时 : 
    <span id="day"></span>天
    <span id="hour"></span>小时
    <span id="min"></span>分钟
    <span id="sec"></span>秒
</p>

步骤2:将数据插入到HTML结构的对应位置

// 获取需要对应插入数据的节点
var day_ele = document.getElementById("day");
var hour_ele = document.getElementById("hour");
var min_ele = document.getElementById("min");
var sec_ele = document.getElementById("sec");

// 封装函数,当数值小于10时在前面加“0”
function addZero( num ){
    if(num < 10){
        return "0" + num;
    }
    return num;
}

// 将数据渲染到页面指定节点中
function renderCountDown(){
    var res = countDown();
    day_ele.innerHTML = addZero(res.day);
    hour_ele.innerHTML = addZero(res.hour);
    min_ele.innerHTML  = addZero(res.min);
    sec_ele.innerHTML  = addZero(res.sec);
}

3、 通过JavaScript原生API(setInterval或setTimeout)实现倒计时效果

setInterval() 与 setTimeout() 都能实现页面倒计时,其区别在于:
setInterval() :每指定间隔时间后执行一次传入的函数,函数会多次执行
setTimeout() :等待指定时间后执行传入的函数,且只执行一次

方法1:使用setInterval()

setInterval(function(){
    renderCountDown();
},1000);
// 可简写为下面这种形式
// setInterval(renderCountDown,1000);

renderCountDown()

方法2:使用setTimeout()

function renderCountDown(){
    var res = countDown();
    hour_ele.innerHTML = addZero(res.hour);
    min_ele.innerHTML  = addZero(res.min);
    sec_ele.innerHTML  = addZero(res.sec);
    setTimeout(renderCountDown, 1000);
}
renderCountDown()

注意:setTimeout()只会执行一次传入的函数。故需要将其放入到渲染函数的内部,从而实现循环调用(类似于递归思想)。


三、代码封装

<p>
    倒计时 : 
    <span id="day"></span>天
    <span id="hour"></span>小时
    <span id="min"></span>分钟
    <span id="sec"></span>秒
</p>
<script>
	// 设置变量(不同的时间传入方式)
	var target_time = new Date("2020/12/31");
	// var target_time = new Date();
	// target_time.setHours(target_time.getHours() + 5);
	
	// 获取需要对应插入数据的节点
	var day_ele = document.getElementById("day");
	var hour_ele = document.getElementById("hour");
	var min_ele = document.getElementById("min");
	var sec_ele = document.getElementById("sec");
	
	// 获取目标时间到当前时间的毫秒数,进行计算并返回结果
	function countDown(){
	    var reduce_ms = target_time.getTime() - Date.now(); 
	    return {
	    	day  : parseInt(reduce_ms / 1000 / 3600 / 24),
	        hour : parseInt(reduce_ms / 1000 / 3600),
	        min  : parseInt(reduce_ms / 1000 / 60 % 60 ),
	        sec  : Math.round(reduce_ms / 1000 % 60)
	    }
	}
	
	// 将数据渲染到页面指定节点中
	function renderCountDown(){
	    var res = countDown();
	    day_ele.innerHTML = addZero(res.day);
	    hour_ele.innerHTML = addZero(res.hour);
	    min_ele.innerHTML  = addZero(res.min);
	    sec_ele.innerHTML  = addZero(res.sec);
	}
	
	// 封装函数,当数值小于10时在前面加“0”
	function addZero( num ){
	    if(num < 10){
	        return "0" + num;
	    }
	    return num;
	}
	
	// 实现倒计时效果
	setTimeout(renderCountDown,1000);
	renderCountDown()
</script>
posted @ 2020-03-08 22:13  qs-cnblogs  阅读(10113)  评论(0编辑  收藏  举报