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>&nbsp;
13 <a href="#">计时器</a>&nbsp;
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">&nbsp;&nbsp;&nbsp;&nbsp;M&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;S&nbsp;</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">开&nbsp;始</button></td>
30 <td><button onclick = "stop()">暂&nbsp;停</button></td>
31 <td><button onclick = "re()">复&nbsp;位</button></td>
32 </tr>
33 </table>
34 </div>
35 </div>
36 <script type="text/javascript" src = "js/time.js"></script>
37 </body>
38 </html>

中间使用了大量的&nbsp;   <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>&nbsp;</span>
22 <input type="button" id = "btn" value="生&nbsp;成" 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 }

感谢您的阅读

原生JS学习之秒表、日历的更多相关文章

  1. 原生js学习 选择dom

    连bootstrap5 都抛弃jquery了,重新使用原生js来写,所以最近在学习原生js. 一.选择dom元素: id let sure=document.getElementById('sure' ...

  2. 【京东详情页】——原生js学习之匿名函数

    一.引言 在js模块中,要给每一个功能封装一个匿名函数.为了更好的理解什么是匿名函数,为什么要用匿名函数,我做了一些查阅和学习. 二.匿名函数 什么是:在创建时,不被任何变量引用的函数. 为什么:节约 ...

  3. 原生js 学习之array 数组

    Array的原生方法:  concat(): 连接两个或更多的数组哦 join(): 把数组的所有元素放在一个字符串中 pop():删除并返回数组的最后一个元素 push():向数组的末尾添加一个元素 ...

  4. 原生js学习笔记2

    知识点: 1:关于this指向问题,如果有函数a(),直接a()那么this指向window,new a()指向函数本身. 2:关于null和undefined.两者如果用“==”则认为两者是相等的, ...

  5. 【学习】原生js学习笔记1:添加class和使input为不可用

    <input type="checkbox" id="new_check" onChange="noUse()" checked> ...

  6. 原生js简易日历效果实现

    这里我们将用原生js实现简易的日历,原理和之前的原生js选项卡差不多,不过也有些区别: 首先html代码: <div class="container"> <di ...

  7. 原生js日历选择器,学习js面向对象开发日历插件

    在web开发过程中经常会碰到需要选择日期的功能,一般的操作都是在文本框点击,然后弹出日历选择框,直接选择日期就可以在文本框显示选择的日期.开发好之后给用户使用是很方便,但如果每一个日历选择器都要临时开 ...

  8. 日历组件 原生js

    自己基于原生js编写的日历组件 git地址: https://github.com/lihefen/calendar.git demo : https://lihefen.github.io/cale ...

  9. 原生JS研究:学习jquery源码,收集整理常用JS函数

    原生JS研究:学习jquery源码,收集整理常用JS函数: 1. JS获取原生class(getElementsByClass) 转自:http://blog.csdn.net/kongjiea/ar ...

随机推荐

  1. JAVA中常见的阻塞队列详解

    在之前的线程池的介绍中我们看到了很多阻塞队列,这篇文章我们主要来说说阻塞队列的事. 阻塞队列也就是 BlockingQueue ,这个类是一个接 口,同时继承了 Queue 接口,这两个接口都是在JD ...

  2. 极客mysql08

    1.innodb支持RC和RR隔离级别实现是用的一致性视图(consistent read view) 2.事务在启动时会拍一个快照,这个快照是基于整个库的. 基于整个库的意思就是说一个事务内,整个库 ...

  3. ubuntu13.04修改默认启动内核

    ubuntu下面的启动内核选项跟其他操作系统不一样,有个子菜单,比如我在默认的ubuntu13.04上安装了一个新的内核3.14.5,那么默认的第一项是3.14.5内核,第二项是一个子菜单,第二项里面 ...

  4. CENTOS 6 配置 yum 安装 nginx

    摘要: 本文介绍如何用yum源安装Nginx,比编译安装简单很多 1.在/etc/yum.repos.d/目录下创建一个源配置文件nginx.repo: cd /etc/yum.repos.d/ vi ...

  5. 【VUE】7.Vuex基本使用

    1. 安装Vuex npm install vuex --save 2. 导入Vuex包 import Vuex from 'vuex' Vue.use(Vuex) 3. 创建store对象 cons ...

  6. bash反弹shell检测

    1.进程 file descriptor 异常检测 检测 file descriptor 是否指向一个socket 以重定向+/dev/tcp Bash反弹Shell攻击方式为例,这类反弹shell的 ...

  7. python应用(2):写个python程序给自己用

    用python写一个程序,然后在命令行上执行,看不到界面(UI),这种程序很常见了,叫命令行程序.然而很多人,特别是不懂程序的人,更需要看到的是一个有界面的,能通过鼠标操作的程序,毕竟已经迈进&quo ...

  8. Java数据结构(七)—— 排序算法

    排序算法(Sort Algorithm) 排序算法介绍和分类 将一组数据,依指定顺序进行排列 排序的分类 内部排序 指将需要处理的所有数据都加载到内部存储器中进行排序 外部排序 数据量过大,无法全部加 ...

  9. Jmeter生成HTML测试报告

    jmeter轻便小巧,运行速度快,但是缺少直观的可视化测试报告,并且生成测试报告操作稍微有点麻烦. GUI界面没有生成测试报告的功能,只能使用命令行生成测试报告.这里需要提到一个jtl的文件,它是生成 ...

  10. Robot Framework安装和入门

    1:安装 python 安装python并且配置好环境变量 2:安装 Robot Framework pip install robotframework 3:安装GUI界面 pip install ...