原生JS学习之秒表、日历
作者:互联网
Tips:涉及知识点:Date setInterval DOM
秒表
效果图:
简单构造出草图
Html代码
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>时间Demo</title> 5 <meta charset="utf-8"> 6 <link rel="stylesheet" type="text/css" href="css/time.css"> 7 </head> 8 <body> 9 <div align="center"> 10 <!-- 导航栏 --> 11 <div id = "nav"> 12 <a href="#">闹钟</a> 13 <a href="#">计时器</a> 14 <a href="#" style="color:white">秒表</a> 15 </div> 16 17 <!-- 时钟 --> 18 <div id = "timer" align="center"> 19 <br> 20 <span id = "title">Timer</span><br> 21 <span id = "tips" class = "timer"> M S </span><br> 22 <span id = "tim" class = "timer">00:00</span><br> 23 <span id = "s" class = "timer">00</span> 24 </div> 25 <!-- 底部按钮 --> 26 <div id = "footer"> 27 <table> 28 <tr> 29 <td><button onclick = "start()" id = "start">开 始</button></td> 30 <td><button onclick = "stop()">暂 停</button></td> 31 <td><button onclick = "re()">复 位</button></td> 32 </tr> 33 </table> 34 </div> 35 </div> 36 <script type="text/javascript" src = "js/time.js"></script> 37 </body> 38 </html>
中间使用了大量的 <br> 是因为我目前不太会调这个细节,只好拿这些来补位
CSS代码
1 body{ 2 background: black; 3 } 4 a{ 5 color:gray; 6 text-decoration:none; 7 font-size:larger; 8 } 9 #nav{ 10 border-bottom:1px solid orange; 11 width: 50%; 12 text-align: left; 13 padding-bottom: 10px; 14 } 15 #timer{ 16 margin-top: 20px; 17 margin-bottom: 20px; 18 height: 250px; 19 width: 250px; 20 border-radius:50%; 21 border:5px dashed skyblue; 22 text-align: center; 23 24 } 25 #title{ 26 color:gray; 27 font-size:xxx-large; 28 } 29 #tim{ 30 font-size:xxx-large; 31 } 32 #tips{ 33 font-size: x-large; 34 } 35 .timer{ 36 color:white; 37 } 38 #s{ 39 font-size:xx-large; 40 } 41 button{ 42 background: orange; 43 color:gray; 44 width: 80px; 45 height: 30px; 46 border: none; 47 outline: none; 48 font-size:large; 49 } 50 button:hover{ 51 color:black; 52 } 53 table{ 54 width: 600px; 55 border-collapse: collapse; 56 border-spacing: 0; 57 table-layout: fixed; 58 text-align:center; 59
除了常见的样式,还加了一些现查的
比如
实现a标签去除原有样式: text-decoration:none;
按钮的边框去除
border: none;
outline: none;
JS实现
思路分析:
我第一下想象到的是Js的计时器,setInterval(),然后每10ms执行一次,然后是纯逻辑判断,不用任何内置对象。后来发现,如果是这样,那么会很复杂,判断条件也很多。
后来想到了Date对象,可以通过点击时与当前时间做差值运算,这样就少了很多边界条件的判断。
首先是取得节点,clc是用来获得计时器的标志位,方便后来停止
1 var time = document.getElementById("tim"); 2 var ss = document.getElementById("s"); 3 var clc = null;
开始按钮点击时进行的操作:
1 function start(){ 2 clearInterval(clc);//防止点击两次之后,无法停止计时器的问题 3 let time2=new Date().getTime(); 4 clc = setInterval(function(){ 5 let times = new Date().getTime() - time2; 6 let minutes=Math.floor(times/60000); 7 let seconds=Math.floor((times-minutes*60000)/1000); 8 let ms=Math.floor((times-minutes*60000-seconds*1000)/10); 9 time.innerText = (minutes<10 ? "0" +minutes : minutes)+":" 10 +(seconds<10 ? "0"+seconds :seconds); 11 ss.innerText = ms<10?"0"+ms:ms; 12 }, 10); 13 }
new Date().getTime() 使用来获取当前时间到1970年1月1日的毫秒数
通过取余,取整,补零等简单的操作,就可以得到时间,然后每10毫秒渲染在页面上一次。
暂停和复位JS
1 function stop(){ 2 clearInterval(clc); 3 } 4 5 function re(){ 6 time.innerText = "00:00"; 7 ss.innerText = "00"; 8 }
到这里,功能基本实现,但是留下了一个疑问
秒表计时是按照点击开始的时间和每过10ms的时间计算得到的,那么再此点击开始,时间就会从0开。
但所给的最终效果只是一个图片,无法判断接下来要实现的功能。
如果扩展的话,可以加上一个参数,就是按下暂停的时间(页面上显示的)。
日历
效果图
这个结构也很明显,所以直接上手
Html代码
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>日历Demo</title> 6 <link rel="stylesheet" type="text/css" href="css/date.css"> 7 </head> 8 <body> 9 <div id = "main" align="center"> 10 <!-- 标题 --> 11 <div id = "title"> 12 <h2>模拟日历</h2> 13 </div> 14 15 <!-- 输入框 --> 16 <div > 17 <span>年</span> 18 <input type="text" id = "year"> 19 <span>月</span> 20 <input type="text" id = "month"> 21 <span> </span> 22 <input type="button" id = "btn" value="生 成" onclick = "fun()"> 23 </div> 24 25 <!-- 日历 --> 26 <div id = "calendar"> 27 28 <div id = "date"> 29 <span id = date2></span> 30 </div> 31 <div> 32 <table border = 0 id = "week" > 33 <tr> 34 <td>Sun</td> 35 <td>Mon</td> 36 <td>Tue</td> 37 <td>Wed</td> 38 <td>Thu</td> 39 <td>Fri</td> 40 <td>Sat</td> 41 </tr> 42 </table> 43 </div> 44 <div id = "month2"> 45 <table id = "day" border ="1" cellpadding="0" cellspacing="0"> 46 <tr> 47 <td></td> 48 <td></td> 49 <td></td> 50 <td></td> 51 <td></td> 52 <td></td> 53 <td></td> 54 </tr> 55 <tr> 56 <td></td> 57 <td></td> 58 <td></td> 59 <td></td> 60 <td></td> 61 <td></td> 62 <td></td> 63 </tr> 64 <tr> 65 <td></td> 66 <td></td> 67 <td></td> 68 <td></td> 69 <td></td> 70 <td></td> 71 <td></td> 72 </tr> 73 <tr> 74 <td></td> 75 <td></td> 76 <td></td> 77 <td></td> 78 <td></td> 79 <td></td> 80 <td></td> 81 </tr> 82 <tr> 83 <td></td> 84 <td></td> 85 <td></td> 86 <td></td> 87 <td></td> 88 <td></td> 89 <td></td> 90 </tr> 91 <tr> 92 <td></td> 93 <td></td> 94 <td></td> 95 <td></td> 96 <td></td> 97 <td></td> 98 <td></td> 99 </tr> 100 </table> 101 </div> 102 </div> 103 </div> 104 105 <script type="text/javascript" src = "js/date.js"></script> 106 </body> 107 </html>
CSS代码
1 body{ 2 background: url(../img/img1.jpg); 3 Background-size:100%; 4 } 5 #main{ 6 margin:30px auto; 7 height: 600px; 8 width: 700px; 9 background: rgba(255,255,255,0.5); 10 } 11 #title{ 12 text-align: left; 13 padding-top: 5px; 14 padding-left: 20px; 15 } 16 #btn{ 17 background: #036; 18 color: white; 19 border: none; 20 outline: none; 21 height: 30px; 22 width: 70px; 23 } 24 input{ 25 height: 25px; 26 width: 180px; 27 } 28 #calendar{ 29 width: 350px; 30 height:auto; 31 margin-top: 10px; 32 } 33 #date{ 34 font-size:x-large; 35 height: 50px; 36 width: 100%; 37 background: #036; 38 border-radius: 5px; 39 margin: 0 auto; 40 color: white; 41 } 42 43 #week{ 44 height: 50px; 45 width: 100%; 46 background: #ccc; 47 text-align: center; 48 font-weight:600; 49 } 50 #week tr td{ 51 width: 50px; 52 } 53 #day{ 54 width:100%; 55 background: #ccc; 56 text-align: center; 57 } 58 #day tr td{ 59 height: 50px; 60 width: 50px; 61 } 62 .t{ 63 background: white; 64 }
这些都做完,一个大概的轮廓就出来了
那么接下来,就是获取输入的年月,并渲染了
JS实现
思路分析
年月的获得,就是节点取值的问题,为了方便后续进行,我加了简单的正则判断
var year_reg = /^\d{1,4}$/; var month_reg = /^1[0-2]$|[1-9]/;
然后我需要几个很关键的数据
首先是上个月的天数,因为在大多数情况下,第一行我需要用灰色显示上个月的几天。
同时考虑到如果是一月,那么上一月的年份也会换,所以也加了判断条件。
var lastDate = parseInt(month==1?31:new Date(year,month-1,0).getDate());
其次是当前月的天数,因为后面要获取到下个月开始的日期
var thisDate = parseInt(new Date(year,month,0).getDate());
然后是当前月第一天的星期
var thisDate_one = parseInt(new Date(year,month-1,1).getDay());
由于最后一个参数不是0,所以月份要-1(取值范围的问题)
然后是复杂的循环的拼(字符)串,这也是日历的核心
1 var str = "<table id = 'day' border ='1' cellpadding='0' cellspacing='0'>"; 2 for(let i = 1;i<=6;i++){ 3 str+="<tr>"; 4 for(let j = 1;j<=7;j++){ 5 if(i==1){ 6 str+=j<thisDate_one+1?"<td>"+(lastDate-thisDate_one+j)+"</td>":"<td class='t'>"+(j-thisDate_one)+"</td>"; 7 }else if(i>=5){ 8 str+=(j-thisDate_one+(i-1)*7)>thisDate?"<td>"+(j-thisDate_one+(i-1)*7)%thisDate+"</td>":"<td class='t'>"+(j-thisDate_one+(i-1)*7)+"</td>"; 9 }else{ 10 str+="<td class='t'>"+(j-thisDate_one+(i-1)*7)+"</td>"; 11 } 12 } 13 str+="</tr>"; 14 } 15 str+="</table>"; 16 day.innerHTML = str; 17 return;
最重要的就是第四行的for循环里面。
会有三种情况,就是首行,中间,尾行(1行或两行)
首行,判断i==1
然后再与第一天的星期相比,小于则执行上个月的循环。
拿2020年8月举例
第一天是周六,那么第一天之前,他的<td>里的数据就是上个月的天数 - 这个月的天数 + j(行号)
即
lastDate-thisDate_one+j
代码上加上了括号是因为NaN的问题
然后当前月的循环就是 行号-当前月的第一天
j - thisDate_one
第二个判断条件是尾行,我们知道从第五行开始,可能就进入了下个月,那么又要重新考虑逻辑
判断是否进入了下个月,需要判断是否大于当前月的天数,这里也使用了一个三目运算
str+=(j-thisDate_one+(i-1)*7)>thisDate?"<td>"+(j-thisDate_one+(i-1)*7)%thisDate+"</td>":"<td class='t'>"+(j-thisDate_one+(i-1)*7)+"</td>";
因为周数的迭代,所以要加上( i - 1 )* 7 同时巧妙的利用取余运算来得出<td>的内容
后面因为小于,按正常计算就可以
中间比较简单
str+="<td class='t'>"+(j-thisDate_one+(i-1)*7)+"</td>";
接下来是完整的JS代码
1 var year_reg = /^\d{1,4}$/; 2 var month_reg = /^1[0-2]$|[1-9]/; 3 4 function fun(){ 5 var year = document.getElementById("year").value; 6 var month = document.getElementById("month").value; 7 if (year_reg.test(year)&&month_reg.test(month)) { 8 document.getElementById("date2").innerText = year+"年"+month+"月"; 9 var thisDate = parseInt(new Date(year,month,0).getDate()); 10 var lastDate = parseInt(month==1?31:new Date(year,month-1,0).getDate()); 11 var day = document.getElementById("month2"); 12 var thisDate_one = parseInt(new Date(year,month-1,1).getDay()); 13 var str = "<table id = 'day' border ='1' cellpadding='0' cellspacing='0'>"; 14 for(let i = 1;i<=6;i++){ 15 str+="<tr>"; 16 for(let j = 1;j<=7;j++){ 17 if(i==1){ 18 str+=j<thisDate_one+1?"<td>"+(lastDate-thisDate_one+j)+"</td>":"<td class='t'>"+(j-thisDate_one)+"</td>"; 19 }else if(i>=5){ 20 str+=(j-thisDate_one+(i-1)*7)>thisDate?"<td>"+(j-thisDate_one+(i-1)*7)%thisDate+"</td>":"<td class='t'>"+(j-thisDate_one+(i-1)*7)+"</td>"; 21 }else{ 22 str+="<td class='t'>"+(j-thisDate_one+(i-1)*7)+"</td>"; 23 } 24 } 25 str+="</tr>"; 26 } 27 str+="</table>"; 28 day.innerHTML = str; 29 return; 30 } 31 alert("输入不合法"); 32 return; 33 }
感谢您的阅读
标签:thisDate,日历,JS,nbsp,str,year,var,month,秒表 来源: https://www.cnblogs.com/keason/p/14016761.html