JavaScript实现仿Clock ISO时钟
本文详细介绍如何利用HTML5、CSS3和JavaScript技术,从零开始构建一个仿ISO风格的模拟时钟。内容涵盖页面布局、CSS3伪元素与动画定义、以及通过JavaScript获取系统时间并计算指针角度的核心逻辑,最终实现具备真实时间显示功能的动态时钟效果。
项目概述
接下来,我们将尝试在网页中还原一个类似ISO系统界面的时钟组件:ISO Clock。
最终实现的视觉效果如下所示:

ISO Clock
项目分析与布局
项目整体分析与规划
第一步,我们需要从本地客户端获取当前的系统时间数据。
第二步,时钟界面包含三个指针,我们可以利用CSS动画技术,使它们围绕中心点持续旋转。
第三步,根据获取到的小时(hour)、分钟(minute)和秒(second)数值,分别计算出时针、分针和秒针对应的旋转角度。
HTML与CSS基础构建
页面布局结构设计
<div class="box">
<article class="clock">
<div class="hours-container">
<div class="hours"></div>
</div>
<div class="minutes-container">
<div class="minutes"></div>
</div>
<div class="seconds-container">
<div class="seconds"></div>
</div>
</article>
</div>
首先,设置一个名为.box的容器,主要用于辅助整体布局定位。
其次,为每个指针分别创建一个对应的容器(如hours-container等),以便独立控制。
CSS样式编写
加载背景图片,并将其放置在页面的合适位置。
html{ font-size: 10px;
}html,body{ margin: 0; padding: 0;
}.box{ width: 35rem; height: 38rem; background: rgb(205,205,205); border-radius: 1rem; margin: 5% auto; display: flex; justify-content: center; align-items: center;
}.clock{ width: 30rem; height: 30rem; background: #fff url(ios_clock.svg) no-repeat center; background-size: 88%; border-radius: 50%; position: relative;
}

设置.box的宽度为35rem,高度为38rem,这一比例在视觉上较为协调。
.box采用Flex布局,确保内部的.clock元素在水平和垂直方向上均居中。熟悉Flex布局的开发者应能轻松理解。
.clock的背景引用了一张图片,具体地址可参考相关资源链接。
中心轴与指针样式
中心轴的实现
利用CSS3的伪元素(:after)为时钟添加一个实心小圆点,所有指针均围绕该点旋转。
.clock:after{ content: ''; width: 1.5rem; height: 1.5rem; background: #000; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); /* 向左上移动自身的50% */
z-index: 10;
}

必须设置content: '';,否则即使指定了宽高,伪元素也不会显示。
由于相对定位默认从元素左上角开始计算,仅设置top: 50%和left: 50%无法使圆点居中。需配合transform: translate(-50%,-50%);,使其向左上方移动自身宽高的一半,从而精确居中。
设置z-index: 10;,确保该小圆点位于视图最上层,以遮挡指针交叉处的杂乱线条。
指针容器的定位
.hours-container,.minutes-container,.seconds-container{ position: absolute; top: 0; right: 0; bottom: 0; left: 0;
}
容器已放置在.clock上方,但暂无具体样式,接下来将创建具体的指针元素。
指针元素的创建
.hours { width: 3%; height: 20%; background: #000; transform-origin: 50% 100%; position: absolute; top: 30%; left: 48.5%;
}.minutes { width: 2%; height: 37%; background: #000; transform-origin: 50% 100%; position: absolute; top: 13%; left: 49%;
}.seconds { width: 1%; height: 40%; background: #f00; transform-origin: 50% 90%; position: absolute; top: 20%; left: 49.5%; z-index: 8;
}

分别构建时针、分针和秒针三个DOM元素。
使用百分比(%)作为单位,可使指针更好地适应不同屏幕尺寸。
设置transform-origin: 50% 90%;,定义指针旋转的轴心点:X轴方向居中,Y轴方向位于90%处(即指针底部附近,具体参考图示)。

在定位时已考虑自身宽度,因此无需再额外向左上角移动。
动画定义与优化
动画效果定义
至此,时钟仅具备静态外观,接下来赋予其动态功能。
定义关键帧动画
@keyframes rotate {
100% { transform: rotateZ(360deg);
}
}
使用@keyframes规则定义名为rotate的动画,使应用该动画的元素沿Z轴(即之前设定的旋转轴心)旋转360度。
定时功能配置
设定各指针旋转一周 360 度所需的时间。
.hours-container { animation: rotate 60s infinite linear;
}.minutes-container { animation: rotate 30s infinite linear;
}.seconds-container { animation: rotate 10s infinite linear;
}

为便于演示,此处使用了固定时间,并未完全遵循真实时钟的物理规律(真实时钟时针应为12小时/43200秒,分针3600秒,秒针60秒)。
优化为更真实的时钟体验
现实中的机械钟通常秒针和分针会呈现跳动效果,并伴随滴答声。我们可以尝试实现这一效果。
.hours-container { animation: rotate 60s infinite linear;
}.minutes-container { animation: rotate 3600s infinite steps(60);
}.seconds-container { animation: rotate 60s infinite steps(60);
}

只需将分针和秒针的动画方式调整为steps()函数即可实现跳动效果。
然而,上述动画每次刷新页面时均从0度开始,无法显示真实时间。如何实现显示当前真实时间的功能呢?
实时时间计算逻辑
实现实时时间显示
首先获取当前系统时间,随后计算每个指针应旋转的具体角度。
获取指针DOM元素
const hourHand = document.querySelector('.hours-container');const minuteHand = document.querySelector('.minutes-container');const secondHand = document.querySelector('.seconds-container');
获取当前时间数据
const now = new Date();const hour = now.getHours();const minute = now.getMinutes();const second = now.getSeconds();
`
计算每个指针应旋转的角度值
在CSS3中,角度单位主要有四种:
- deg(度,圆周360度)
- grad(梯度,圆周400梯度)
- turn(转/圈,圆周1圈)
- rad(弧度,圆周2π弧度)
- 它们之间的换算关系如下:
90deg = 100grad = 0.25turn ≈ 1.570796326794897rad
显然,本例中我们需要使用的单位是deg(度)。
const secondDegree = second * 6 + 90;
const minuteDegree = minute * 6 + (second / 10) + 90;
const hourDegree = (hour * 30) + (minute / 2) + 90;
公式中+90的原因是:CSS角度起始位置为水平X轴(3点钟方向),而时钟指针默认指向Y轴(12点钟方向),需统一坐标系。
秒针计算最简单,公式为:(second / 60) * 360 + 90;。
分针需考虑秒针的影响(如过了30秒,相当于走了半分钟)。公式为:((minutes/ 60) * 360) + ((seconds / 60) * 6) + 90;。
时针计算稍复杂,需考虑分钟的影响(如过了30分钟,相当于走了半小时)。公式为:(( hours/ 12) * 360) + ((minutes / 60) * 30) + 90;。
应用计算出的角度值
hourHand.style.transform = `rotateZ(${hourDegree}deg)`;
minuteHand.style.transform = `rotateZ(${minuteDegree}deg)`;
secondHand.style.transform = `rotateZ(${secondDegree}deg)`;
为使页面实时更新,需将上述逻辑封装为函数,并通过定时器每秒执行一次。
至此,整个时钟的功能已全部实现!
JS怎么实现页面强制刷新
2026-11-05 14:53:38
点击JS链接直接运行不下载?前端实现.js文件强制下载的三种方法
2026-11-05 12:12:23
怎么封装一个通用的JS创建元素辅助函数
2026-11-05 11:41:41
Swiper.js 怎么监听滑动结束并获取当前索引
2026-11-05 10:57:15
HTML、CSS和JS的关系:Web前端三件套怎么协作
2026-11-04 15:41:40
