『 实战』从0到1,带你开发开发一款令人惊叹的时钟特效
前言
我们在最初学 js
的时候,经常会遇到 Date
对象,它主要用于获取一些日期和时间相关的数据,包括当前的时分秒、年月日等等,而我们常常使用 Date
练手的项目就是开发一个简单的时钟或者获取当前年月日的组件,今天给大家带来一款效果令人惊叹的时钟,让我们先来看一下相关的效果,如下:
通过上述的动态图,我们可以看到这个时钟特效包含两个部分,上面是基础的时钟特效,下面是一个动态时间,虽然这个效果看起来不难,但是它的细节还是有很多的,下面我们就一起来学习一下吧!
表盘
首先我们将表盘画出来,这里主要用到了 CSS
中的 border-radius
属性,并且我们要将表盘的指针的起点固定在正中心,就需要用到 CSS
中的 flex
布局,关于 flex
布局,引用 MDN 的话来说:
Flexible Box 模型,通常被称为 flexbox,是一种一维的布局模型。它给 flexbox 的子元素之间提供了强大的空间分布和对齐能力。
由于 flex
布局是一维的布局模型,因此我们可以通过 flex-direction
改变元素的排列方式,flex-direction
的默认值是 row
,意思是按行(即X轴排列),我们可以通过修改 row
为 column
来改变它的排列方式为列(即Y轴排列),并且根据排列方式的不同,我们可以设置行或列中元素的位置,常见的属性有 align-items
和 justify-content
,这里我们需要将整个表盘居中显示,就需要设置这两个属性的值为 center
,下面我们一起来看一下表盘的实现。
表盘
首先画出最外层的表盘,相关 html
代码如下:
<div class="container">
<div class="clock">
<span><b>1</b></span>
<span><b>2</b></span>
<span><b>3</b></span>
<span><b>4</b></span>
<span><b>5</b></span>
<span><b>6</b></span>
<span><b>7</b></span>
<span><b>8</b></span>
<span><b>9</b></span>
<span><b>10</b></span>
<span><b>11</b></span>
<span><b>12</b></span>
</div>
</div>
首先我们需要将 container 进行居中,并且给它设置一个背景色,然后添加相关的阴影。在 CSS
中,我们可以通过 box-shadow
来给一个元素添加阴影,box-shadow
有多个参数,这里借助 MDN 官方的介绍,如下:
- 当给出两个、三个或四个
<length>
值时。
- 如果只给出两个值,那么这两个值将会被当作
<offset-x><offset-y>
来解释。- 如果给出了第三个值,那么第三个值将会被当作
<blur-radius>
解释。- 如果给出了第四个值,那么第四个值将会被当作
<spread-radius>
来解释。- 可选,
inset
关键字。- 可选,
<color>
值。
上面的介绍是什么意思呢?别急,我们写几个例子就明白了。
当 box-shadow
有两个参数时:box-shadow: 10px 10px;
这两个值就分别代表 X轴 和 Y轴 方向的阴影渲染偏移,默认颜色是白色,如图所示:
当 box-shadow
有三个参数时:box-shadow: 10px 10px 10px;
最后一个值表示阴影模糊半径,如下图所示:
当 box-shadow
有四个参数时:box-shadow: 10px 10px 10px 10px;
最后一个值表示阴影扩散半径,如下图所示:
因为上面的示例中我们没有添加 color 选项,因此默认是阴影是白色的。我们可以通过添加相关的颜色值来改变阴影的颜色,这里就不做演示了。
我们继续回到 container
中来,通过添加如下样式,就能搭建一个基础的表盘,代码如下:
//less
.container {
position: relative;
background: #2f363e;
border-radius: 20px;
border-top-left-radius: 225px;
border-top-right-radius: 225px;
// 通过 box-shadow 设置表盘的阴影,而 box-shadow 属性是可以叠加的,多个阴影通过逗号进行分割
box-shadow: 25px 25px 75px rgba(0, 0, 0, .75),
10px 10px 70px rgba(0, 0, 0, .25),
inset 5px 5px 20px rgba(255, 255, 255, .2),
inset -5px -5px 15px rgba(0, 0, 0, .75);
// 通过 flex 布局将整个表盘展示在页面正中间
display: flex;
justify-content: center;
align-items: center;
.clock {
position: relative;
width: 450px;
height: 450px;
background: #2f363e;
border-radius: 50%;
box-shadow: 10px 50px 70px rgba(0, 0, 0, .25),
inset 5px 5px 10px rgba(0, 0, 0, .5),
inset 5px 5px 20px rgba(255, 255, 255, .2),
inset -5px -5px 15px rgba(0, 0, 0, .75);
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 30px;
}
}
通过设置表盘的基础样式,我们可以得到如下的一个基础表盘:
在上面的代码中,因为使用了 box-shadow
属性,并且叠加了四层阴影,因此让整个表盘看起来就像是一个 3D
的表盘,我们在日常的开发中就可以通过多次叠加 box-shadow
属性值从而来得到一个令人满意的阴影效果。
我们在上面看到表盘的数字还没有样式,都挤在中间的区域,之所以挤在中间,是因为我们前面介绍过使用 flex
布局默认的布局方式就是 row
,并且设置了 justify-content
和 align-items
的值为 center
,因此所有的数字都挤在中间,并且是横向沿着 X轴 排列的,这就是 flex
最基础的布局。
下面我们让整个表盘的数字按照正常的刻度来展示,在添加数字刻度之前,我们还需要修改一下相关的 html 代码,因为我们并不知道每个数字所在的位置,一般我们如果用 js 计算,就是用 360 / 12 来获取每个刻度的弧度,然后进行设置,这里我们还是用前面文章中介绍的 var 来进行获取。首先修改相关 html 如下:
<!-- 时钟数值 -->
<span style="--i:1;"><b>1</b></span>
<span style="--i:2;"><b>2</b></span>
<span style="--i:3;"><b>3</b></span>
<span style="--i:4;"><b>4</b></span>
<span style="--i:5;"><b>5</b></span>
<span style="--i:6;"><b>6</b></span>
<span style="--i:7;"><b>7</b></span>
<span style="--i:8;"><b>8</b></span>
<span style="--i:9;"><b>9</b></span>
<span style="--i:10;"><b>10</b></span>
<span style="--i:11;"><b>11</b></span>
<span style="--i:12;"><b>12</b></span>
然后我们继续来写刚才的样式,如下:
// less
span {
position: absolute;
inset: 20px;
color: #fff;
text-align: center;
// 在上面说过,我们计算的方式是 360 / 12 ,因此每一个数组的旋转角度就是 30 * 它是第几个
transform: rotate(calc(30deg * var(--i)));
b {
font-size: 2em;
opacity: .5;
font-weight: 600;
display: inline-block;
// span 内部的文字要朝反方向旋转,不然数字的朝向就会展示错误
transform: rotate(calc(-30deg * var(--i)));
}
}
通过上面的修改,我们可以得到如下的效果:
接下来我们需要画出中间的指针以及相关的表盘轮,修改一下 html
,代码如下:
<div class="clock">
<!-- 时间刻度 -->
<div class="circle" style="--clr:#04fc43" id="sc"><i></i></div>
<div class="circle min-circle" style="--clr:#fee800" id="mn"><i></i></div>
<div class="circle sec-circle" style="--clr:#ff2972" id="hr"><i></i></div>
<!-- 时钟数值 -->
</div>
其中我们在三个 div
中添加了行间的 style
,主要用来设置这三个圆的颜色,添加相关的 CSS
样式,代码如下:
.circle {
position: absolute;
width: 300px;
height: 300px;
border: 2px solid rgba(0, 0, 0, .25);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: flex-start;
z-index: 10;
&.min-circle {
width: 240px;
height: 240px;
z-index: 9;
}
&.sec-circle {
width: 180px;
height: 180px;
z-index: 8;
}
> i {
position: absolute;
width: 6px;
height: 50%;
background: var(--clr);
opacity: .5;
transform-origin: bottom;
transform: scaleY(.5);
}
&:nth-child(1) {
i {
width: 2px;
}
}
&:nth-child(2) {
i {
width: 6px;
}
}
&::before {
content: '';
position: absolute;
top: -8.5px;
// left: 5%;
width: 15px;
height: 15px;
border-radius: 50%;
background: var(--clr);
box-shadow: 0 0 20px var(--clr), 0 0 60px var(--clr);
}
}
在上面的 CSS
代码中,我们只需要注意将每一个圆环里面的 i
标签的变换位置设置为 bottom
即可,这样我们设置元素是缩放时,都会以底部为起点,而不会从中心开始缩放,实现的效果如下图所示:
这个色彩艳丽的表盘已经有了,接下来还有下面的电子时钟,我们接着盘!
电子时钟
因为表盘和时钟是分开的,因此我们还需要添加时钟相关的 html,代码如下:
<!-- 底部时间 -->
<div class="time">
<div id="hours" style="--clr:#04fc43">00</div>
<div id="minutes" style="--clr:#fee800">00</div>
<div id="seconds" style="--clr:#ff2972">00</div>
<div id="ampm">AM</div>
</div>
在这个电子时钟里面,我们额外添加了一个当然是上午还是下午的展示,因为我们的时间展示是按12小时制的,因此会区分当前的上午还是下午,接着我们添加一下电子时钟的 CSS 样式,代码如下:
.time {
margin-bottom: 40px;
display: flex;
padding: 10px 20px;
font-size: 2em;
font-weight: 600;
border: 2px solid rgba(0, 0, 0, .5);
border-radius: 40px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, .5),
inset 5px 5px 20px rgba(255, 255, 255, .2),
inset -5px -5px 15px rgba(0, 0, 0, .75);
div {
position: relative;
width: 60px;
text-align: center;
font-weight: 500;
color: var(--clr);
&:nth-child(1), &:nth-child(2) {
&::after {
content: ':';
position: absolute;
right: -4px;
}
}
&:last-child {
font-size: .5em;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
}
&:nth-child(2) {
&::after {
animation: animate 1s steps(1) infinite;
}
}
}
}
@keyframes animate {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
}
在这个 CSS 的最后面,添加了一个动画,这个动画主要用于电子时钟的秒针跳动,我们可以看一下实现的效果,如图:
样式写到这里,这个炫酷的时钟已经完成了静态的内容,接下来我们就需要让整个时钟能够真正的动起来,并且实时获取到当前的时间。
动态电子时钟
在最开始也介绍过在 js
中我们常用的 Date
,这里我们需要借助 Date
来获取当前日期的时分秒,然后将对应的时间展示在时钟里。
关于 Date
,我们还是先来看一下 MDN 官方文档,引用官方的介绍如下:
Date
对象则基于 Unix Time Stamp,即自 1970 年 1 月 1 日(UTC)起经过的毫秒数。
创建一个 Date
对象的唯一方法是通过new
操作符,写法如下:
const date = new Date()
创建出来的 date
对象,上面包含很多方法,包括 date.getHours
、date.getMinutes
、date.getSeconds
等,当然还有更多的方法,如果对 Date
不熟悉的童鞋,可以点击这里进行查看。
我们只需要借助上述的三个 API
即可获取到当前的时分秒,相关的 js
代码如下:
...other code
constructor() {
this.hr = document.getElementById('hr');
this.mn = document.getElementById('mn');
this.sc = document.getElementById('sc');
this.hours = document.getElementById('hours');
this.minutes = document.getElementById('minutes');
this.seconds = document.getElementById('seconds');
this.ampm = document.getElementById('ampm');
this.init();
}
getClock() {
const day = new Date();
const hh = day.getHours() * 30;
const mm = day.getMinutes() * 6;
const ss = day.getSeconds() * 6;
this.hr.style.transform = `rotateZ(${hh + (mm / 12)}deg)`;
this.mn.style.transform = `rotateZ(${mm}deg)`;
this.sc.style.transform = `rotateZ(${ss}deg)`;
}
...other code
通过获取到当前的时分秒,然后设置对应元素的 transform
属性,即可在时间发生改变后修改当前元素展示的形态,实现的效果如下图所示:
时钟的效果实现了,接下来还剩下底部的电子钟了。电子钟的效果其实也是借助了 Date
对象,使用的方法跟上面的类似,相关 js
代码如下:
...other code
getTimer() {
let h = new Date().getHours();
let m = new Date().getMinutes();
let s = new Date().getSeconds();
let am = h >= 12 ? 'PM' : 'AM';
if (h > 12) {
h = h - 12;
}
h = (h < 10) ? '0' + h : h;
m = (m < 10) ? '0' + m : m;
s = (s < 10) ? '0' + s : s;
this.hours.innerHTML = h;
this.minutes.innerHTML = m;
this.seconds.innerHTML = s;
this.ampm.innerHTML = am;
}
...other code
其中需要注意的,也仅仅只是判断当前的时间是上午还是下午,通过获取当前的小时,根据12小时时间制来区分就可以了,最终的实现效果在这里进行查看:
总结
通过学习 js
中的 Date
对象,实现了一个时钟特效,当然 Date
本身还有很多其它的属性,不仅仅可以获取当前的时分秒,还可以获取当然的年月日,并且像一些第三方库,例如:moment.js
、dayjs
,都是通过 Date
对象来实现相关的时间及日期的获取,因此我们还是有必要掌握 Date
相关的使用的。
最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家
往期回顾
转载自:https://juejin.cn/post/7146121729767964680