No.25

做一个计时器的总结

  • 使用上方的HTML结构(可以根据需要自行微调)为基础编写JavaScript代码
  • 当变更任何一个select选择时,更新 result-wrapper 的内容
  • 当所选时间早于现在时间时,文案为 现在距离 "所选时间" 已经过去 xxxx
  • 当所选时间晚于现在时间时,文案为 现在距离 "所选时间" 还有 xxxx
  • 注意当前时间经过所选时间时候的文案变化
  • 注意选择不同月份的时候,日期的可选范围不一样,比如1月可以选31天,11月只有30天,注意闰年
  • 同样,需要注意,通过优雅的函数封装,使得代码更加可读且可维护


    计时器

一 思路

  • 先设置六个选择框的值,分别用循环函数insertNode(start,end,parentNode)插入节点注意月份值有30、31和是否闰年2月29、28的变化
  • 其次为了获得结果是天时分秒,所以用当前时间-选择框的时间的秒数,可以用得到的秒数得出天数(86400s)创建pastOrFutureTime()函数
  • 每次点击年和月的时候日期都会发生变化,所以为两者创建一个改变时间
  • 把结果输出

二 总结

  1. 把所有的代码放在一个(function init(){ ....... })();的匿名自执行的函数中,可以不会生成全局变量,并且局部变量使用完之后所占的空间就会被回收了,多多把代码放进函数
  2. 迅雷的插件会造成Cannot read property ‘nodeName’ of null解决办法删除即可
  3. 计数器setinterval()如果要在一个函数中自动调用的话,需要在函数之外最少执行一次才会出发函数内部的计时器。
  4. 也可以在外面创建一个函数用计时器执行它
function update(){
    result.innerHTML=pastOrFutureTime();
}
setInterval(update,1000);

三 具体分解如下

insertNode(start,end,parentNode)为了插入不同的值,因为每个选择框插入的值有差别,所以传入start和end控制长度,parentNode是控制父节点的类型。

                var yearNode=document.querySelector("#year-select");
                var monthNode=document.querySelector("#month-select");
                var dayNode=document.querySelector("#day-select");
                var hourNode=document.querySelector("#hour-select");
                var miniteNode=document.querySelector("#minite-select");
                var secondNode=document.querySelector("#second-select");
                var result=document.querySelector("#result-wrapper");
                function insertNode(start,end,parentNode)//父节点,开始和结束值
                {
                    for(var i=start;i<=end;i++)
                    {
                        var node=document.createElement("option");
                        node.innerHTML = i;
                        parentNode.appendChild(node);
                    }
                }
                        insertNode(1997, 2032, yearNode);
                        insertNode(1, 12, monthNode);
                        insertNode(0, 23, hourNode);
                        insertNode(0, 59, miniteNode);
                        insertNode(0, 59, secondNode);
                        insertNode(1,setMonthDays(), dayNode);

1年月和时分秒都是固定值,只有月份里面的天数是不固定的,有1、3、5、7、8、10、12每月天数为31天,4、6、9、11月的天数为30,闰年的2月为29天,非闰年则为28天。所以用一个setMonthDays()swith语句可以方便的创建2月之外的天数,再用一个判断是否为闰年的函数isLeapYear(year),来为2月赋值。

function isLeapYear(year) {
                            return (year % 100 != 0 && year % 4 == 0) || (year % 400 == 0);//0 is false,大于0 is TRUE
                        }
                        function setMonthDays() {
                            var year = yearNode.value,
                            month = monthNode.value;
                            var days=0;
                            switch(month) {
                                case "1":
                                case "3":
                                case "5":
                                case "7":
                                case "8":
                                case "10":
                                case "12": days=31;
                                break;
                                case "2":if(isLeapYear(year)) {
                                    days=29;
                                }
                                else{
                                    days=28;
                                }
                                break;
                                case "4":
                                case "6":
                                case "9":
                                case "11": days=30;
                                break;
                            }
                            return days;
                        }

为年月创建点击事件来触发每月日期天数的变化,并且改变一次之前需要把原来的插入的节点给清空,设置值为空

window.onchange=function(e){
                        if(e.target==monthNode){
                            dayNode.innerHTML="";
                            insertNode(1,setMonthDays(), dayNode);
                        }
                        if(e.target==yearNode){
                            dayNode.innerHTML="";
                            insertNode(1,setMonthDays(), dayNode);
                        }
                    }

计算距离过去和未来的时间,需要用毫秒数来计算时间,首先取得选择框的值,和当前时间,创建选择框日期直接用new Date(year,month,....)就行,如果用UTC否则返回的毫秒数有误差。
如果现在时间毫秒数大于选择时间,则用now - select,否则用select - now,在这计算天数seconds / 86400需要取Math.floor()上取约数,否则会造成误差

var str="";
                    function pastOrFutureTime(){
                        var startNow = Date.now(),//现在时间距离1970年的秒数
                        selectSeconds,//选择的时间距离1970年的秒数
                        intervalSeconds,//现在时间减去选择的时间的间隔秒数
                        yearSelect=Number(yearNode.value),
                        monthSelect=Number(monthNode.value)-1,
                        daySelect=Number(dayNode.value),
                        hourSelect=Number(hourNode.value),
                        minitesSelect=Number(miniteNode.value),
                        secondsSelect=Number(secondNode.value),
                        diffday,
                        diffhour,
                        diffminite,
                        diffsecond,
                        flag;//命名区别符号在前面,相同者在后面比如
                        selectSeconds=new Date(yearSelect, monthSelect, daySelect, hourSelect, minitesSelect, secondsSelect);
                        
                        if(selectSeconds < startNow)
                        {
                            intervalSeconds = (startNow - selectSeconds) / 1000;
                            flag=1;
                        }
                        if(selectSeconds>startNow){
                            intervalSeconds = (selectSeconds - startNow) / 1000;
                            flag=2;
                        }
                        diffday = Math.floor(intervalSeconds / 86400);
                        intervalSeconds = intervalSeconds % 86400;
                        diffhour = Math.floor(intervalSeconds / 3600);
                        intervalSeconds =  intervalSeconds % 3600;
                        diffminite =Math.floor(intervalSeconds / 60);
                        intervalSeconds = intervalSeconds % 60;
                        diffsecond =Math.floor(intervalSeconds);
                        if(flag==1){
                            str="现在距离 " + yearSelect +"年" + (monthSelect+1) + "月" + daySelect + "日" +weeks[selectSeconds.getDay()]+ " 已经过去" + diffday + "天" + diffhour +"小时" + diffminite + "分" +diffsecond + "秒";
                        }
                        if(flag==2){
                            str="现在距离 " + yearSelect +"年" + (monthSelect+1) + "月" + daySelect + "日" +weeks[selectSeconds.getDay()]+ " 还有" + diffday + "天" + diffhour +"小时" + diffminite + "分" +diffsecond + "秒";
                        }
                        result.innerHTML=str;
                        setInterval(pastOrFutureTime,1000);
                    }
                    pastOrFutureTime();
                    result.innerHTML=str;

下面为全部代码




    
        
        
    
    
        
        
        
        
        
        
        
        
        
        
        
        
        

现在距离 2001年1月1日星期X HH:MM:SS 还有 X 天 X 小时 X 分 X 秒

你可能感兴趣的:(No.25)