当前位置: 首页 > news >正文

手把手实现一个进度条时钟,麻麻再也不用担心我把时间看茬了

前言

挂钟大家都知道吧,它通过时针、分针和秒针来表示时间,想当初小学刚开始教怎么看时钟的完全看不懂。今天带大家一步步实现一个类进度条时钟的效果,更直观的知晓当前的时间。

本文将会带大家学到以下知识点:

1.垂直水平居中方式
2.gap 属性搭配 flex 布局 实现等边距
3.Date 日期函数的使用及注意点
4.CSS 变量的简单应用
5.svgcircle 标签的用法
6.stroke-dashoffset 属性和 stroke-dasharray 属性能够的用法

样式重置

首先老规矩,我们将 CSS 样式重置 ,方便各个浏览器统一展示效果。

* {margin: 0;padding: 0;box-sizing: border-box;
} 

背景调整

接下来通过添加 min-height: 100vh 属性,将 body 限制为 视口大小 且通过 overflow: hidden 来将 超出部分隐藏

body {display: flex;justify-content: center;align-items: center;min-height: 100vh;background-color: #2f363e;
} 

这里为了将我们的时钟在屏幕中间展示,我们需要使用 flex 布局body 设置为 水平垂直居中 。同样的,小伙伴们还可以使用 light-heighttransform 等手段实现。

时间绘制

接下来我们要准备 4 个 div ,用来作为展示时间的容器。

<body><div id="time"><div class="circle"><div id="hours">00</div></div><div class="circle"><div id="minutes">00</div></div><div class="circle"><div id="seconds">00</div></div><div class="ap"><div id="ampm">00</div></div></div>
</body> 

然后给其宽高。

#time {display: flex;color: #fff;
}
#time .circle {position: relative;width: 150px;height: 150px;
} 

细心的小伙伴一定注意到了这段 CSS 中有个比较特别的属性:gap。这有什么用呢?

我们来看看 MDN 对 gap 属性的描述:

CSS gap 属性是用来设置网格行与列之间的间隙(gutters),该属性是 row-gapcolumn-gap 的简写形式。

gap 属性它适用于 multi-column elements, flex containers, grid containers,也就是多列布局、弹性布局以及网格布局中(知识点++)。因此这里我们用 flex 布局 搭配 gap 是完全行得通的。

我们看看此时的效果如何:

我们发现最后一个用来表示上午下午的字体有点大,我们将其调小,同时通过 translateY 属性将该元素偏移 -20px(负数表示向上偏移,正数表示向下偏移),和时间做区分。

#time .ap {position: relative;font-size: 1em;transform: translateY(-20px);
} 

这样美观了许多,主次分明。

动态时间

接下来我们要让时间变成实时的,因此我们要用到 Javascript 的 Date 函数了。

1.通过 getHours() 获取当前小时数。
2.通过 getMinutes() 获取当前分钟数。
3.通过 getSeconds() 获取当前秒钟数。

这里有个注意点,通过以上三个方法获取的时间值,都是不带前缀 0 的,并且是 number 类型。什么意思呢?

比如现在是下午的 14:07:04 ,通过 getMinutes() 获取的分钟数是 7 而不是 07,同理,通过 getSeconds()getHours() 获取的时间也是如此。

因此为了美观,我们需要手动给 10 以内 的时间值 补一个 0。具体怎么做呢?这里我用到了字符类型的 padStart 方法,它传递两个参数,分别是数字最后要填充到这个指定的位数,以及用来填充的字符。

为了将 7 变成 07,我们需要将 number 类型的 7 变为字符串类型的 ‘7’,然后执行 ‘7’.padStart(2, 0)。

除此之外,对于 AM 以及 PM 的区分,我们通过判断 getHours() 的返回值是否大等于 12。如果大于则为 PM,否则是 AM。

处理完数据之后通过修改 innerHTML 的值来改变页面上展现的时间,同时通过 setInterval 来不断执行该操作,实现实时更新时间的效果。

<script>let hours = document.querySelector('#hours');let minutes = document.querySelector('#minutes');let seconds = document.querySelector('#seconds');let ampm = document.querySelector('#ampm');setInterval(() => {let h = `${new Date().getHours() % 12}`.padStart(2, 0);let m = `${new Date().getMinutes()}`.padStart(2, 0);let s = `${new Date().getSeconds()}`.padStart(2, 0);let am = h >= 12 ? 'PM' : 'AM';hours.innerHTML = h + '\n<div class="tip">HOURS</div>';minutes.innerHTML = m + '\n<div class="tip">MINUTES</div>';seconds.innerHTML = s + '\n<div class="tip">SECONDS</div>';ampm.innerHTML = am;}, 1000);
</script> 

注意点小结:

1.getHours、getMinutes 以及 getSeconds 返回 number 类型的值(不带前缀 0)
2.padStart 是字符类型的方法,注意先将类型转为 string 再进行调用。

我们来看看效果:

画圆

接下来我们要对每个时间的容器都画一个圆的效果,这里我使用了 svg 标签。原因下文会提。

有的小伙伴可能对 svg 标签比较陌生,确实平时开发的时候用的比较少,实际上它和我们普通的标签差不多,而且也能用过 CSS 设置它的一些属性。

这里画圆我们需要用到 circle 标签,其中,cxcy 属性共同确定了一个圆心的位置,r 属性表示待绘制圆的半径。

<div id="time"><div class="circle" style="--clr: #ff2972"><svg><circle cx="70" cy="70" r="70"></circle></svg><div id="hours">00</div></div><div class="circle" style="--clr: #fee800"><svg><circle cx="70" cy="70" r="70"></circle></svg><div id="minutes">00</div></div><div class="circle" style="--clr: #04fc43"><svg><circle cx="70" cy="70" r="70"></circle></svg><div id="seconds">00</div></div>
</div> 

可以看到默认情况下,circle 标签的背景色是黑色的,我们给它点样式。

#time .circle svg circle {width: 100%;height: 100%;fill: transparent;stroke: #191919;stroke-width: 4;
} 

fill 属性表示当前填充 circle 标签应当用什么颜色(实际上就是背景色的意思)。

stroke 属性表示绘制一个边线(实际上就是边框)。

stroke-width 属性一般搭配 stroke 属性一起用,表示边线的宽度。

经过这么一手修改后已经有模有样了,但是别急,最麻烦的部分要来了。接下来我们要模拟时间进度条了。

模拟进度条

这里我们模拟进度条需要在每个 svg 标签下再添加一个 circle 标签。

<div id="time"><div class="circle" style="--clr: #ff2972"><svg><circle cx="70" cy="70" r="70"></circle><circle cx="70" cy="70" r="70" id="hh"></circle></svg><div id="hours">00</div></div><div class="circle" style="--clr: #fee800"><svg><circle cx="70" cy="70" r="70"></circle><circle cx="70" cy="70" r="70" id="mm"></circle></svg><div id="minutes">00</div></div><div class="circle" style="--clr: #04fc43"><svg><circle cx="70" cy="70" r="70"></circle><circle cx="70" cy="70" r="70" id="ss"></circle></svg><div id="seconds">00</div></div>
</div> 

同时,通过 CSS 变量给这个新增的 circle 标签各不相同的颜色。

#time .circle svg circle:nth-child(2) {stroke: var(--clr);
} 

此时效果如下:

接下来我们要用到一个新的属性:stroke-dasharray

我们来看看 MDN 对 stroke-dasharray 属性的介绍:

属性 stroke-dasharray 可控制用来描边的点划线的图案范式。

是不是有点懵,我们看看下面这张动图:

这是 stroke-dasharray 属性值从 0 开始不断增加的效果。那我们就知道了,实际上这个属性就是控制点划线的长度用的。

那它和我们的进度条有什么关系呢?

不要急,要实现我们的进度条,还需要另一个属性:stroke-dashoffset

我们来看看 MDN 对 stroke-dashoffset 属性的介绍:

属性 stroke-dashoffset 指定了 dash 模式到路径开始的距离。

话不多说,上图:

这是 stroke-dashoffset 属性值从 0 开始不断增加的效果,是不是很像进度条在跑?

我们就是通过 Javascript 动态修改 stroke-dashoffset 来达到进度条跟着时间一起跑的效果!

let hh = document.querySelector('#hh');
let mm = document.querySelector('#mm');
let ss = document.querySelector('#ss');

setInterval(() => {...hh.style.strokeDashoffset = 440 - (440 * h) / 12;mm.style.strokeDashoffset = 440 - (440 * m) / 60;ss.style.strokeDashoffset = 440 - (440 * s) / 60;
}, 1000); 

最后

整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

相关文章:

  • 多模态AI技术详解:跨越数据边界的智能未来
  • CAD中的spline详解
  • 数据库语言、SQL语言、数据库系统提供的两种语言
  • 前端面试常见手写题
  • 37拼购:电商新风尚,共享双赢的购物革命
  • 基于Linux的ARMxy工控机IEC61850协议实践
  • 跟着cherno手搓游戏引擎【25】封装2DRenderer,封装shader传参,自定义Texture
  • 30天自制操作系统(第21天)
  • 学习JAVA的第四天(基础)
  • QT C++实战:实现用户登录页面及多个界面跳转
  • 回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测
  • 安防视频监控平台EasyNVR级联视频上云管理平台EasyNVS,出现报错“i/o deadline reached”该如何解决?
  • java毕业设计潮购购物网站Mybatis+系统+数据库+调试部署
  • Verilog写状态机的三种描述方式之二段式
  • 【正点原子I.MX6U-MINI应用篇】1、编写第一个应用App程序helloworld
  • 【Vue】父子组件通信
  • AI 应用的全流程存储加速方案技术解析和实践分享
  • 云服务器的介绍
  • 《大数据分析技术》课程设计
  • unity urp 实现衣服上面片的效果
  • Spring Boot核心之基本配置、日志配置、自动配置、条件注解
  • 智能手术机器人起源及应用(一)
  • 20分钟学会git基本操作,创建远程仓库
  • keepalived实现nginx负载均衡机高可用
  • STL常用容器——stack容器的使用
  • 基于Dijkstra、A*和动态规划的移动机器人路径规划(Matlab代码实现)
  • 【C语言】文件操作(万字详解,教你掌握文件操作)
  • 【数据结构】-----二叉树(递归、层次实现二叉树的遍历)
  • Java安全框架(课时二十三)笔记内容十三
  • 一种更优雅书写Python代码的方式
  • Linux学习-02-Linux的安装
  • PicoDet 训练自己的数据集(COCO)