前端例程20210731:圆形表盘时钟布局实现

目的

圆形表盘时钟是界面应用中偶尔会涉及到的东西,圆形表盘时钟实现过程中相对复杂的是其布局,这篇文章将对相关实现做个说明。

在这里插入图片描述

布局说明

基础准备

首先准备一个基本的表盘:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <style>
        /* 时钟基本样式 */
        .clock {
            width: 400px;
            height: 400px;
            border-radius: 50%;
            background-color: lightcyan;
            display: grid;
            place-items: center;
        }
        
        /* 时钟表盘样式 */
        .clock .dial {
            width: 90%;
            height: 90%;
            border-radius: 50%;
            display: grid;
            place-items: center;
            /* 与下面position: absolute;配合使用,使下面元素都以本容器为父容器进行绝对定位 */
            position: relative;
        }
    </style>
</head>

<body>
    <div class="clock">
        <div class="dial">
            <div class="num"><span>1</span></div>
            <div class="num"><span>2</span></div>
            <div class="num"><span>3</span></div>
            <div class="num"><span>4</span></div>
            <div class="num"><span>5</span></div>
            <div class="num"><span>6</span></div>
            <div class="num"><span>7</span></div>
            <div class="num"><span>8</span></div>
            <div class="num"><span>9</span></div>
            <div class="num"><span>10</span></div>
            <div class="num"><span>11</span></div>
            <div class="num"><span>12</span></div>
            <div class="point"></div>
            <div class="hand hour" id="handhour"><span></span><span></span></div>
            <div class="hand minute" id="handmin"><span></span><span></span></div>
            <div class="hand second" id="handsec"><span></span><span></span></div>
        </div>
    </div>
</body>

</html>

对于圆形表盘时钟来说其元素一般来说就是圆周上的数字和中间的指针这些,上面代码中我还放置了个point。

数字定位

数字的定位主要使用绝对定位加旋转实现,先看下面演示:

在这里插入图片描述

上图中将数字区域变为绝对定位,这样数字区域就从原先的全都在中间变成一长条,并且数字在最左边。因为前面部分的CSS设置,所有区块都居中在表盘中间,即原点在中心,所以我们可以将数字区域所在的长条进行旋转来将数字本身定位到圆周。定位部分代码如下:

        /* 数字区域定位 */
        .clock .dial .num {
            position: absolute;
            width: 100%;
        }

        .clock .dial .num:nth-child(1) {
            transform: rotate(120deg);
        }

        .clock .dial .num:nth-child(2) {
            transform: rotate(150deg);
        }

        .clock .dial .num:nth-child(3) {
            transform: rotate(180deg);
        }

        .clock .dial .num:nth-child(4) {
            transform: rotate(210deg);
        }

        .clock .dial .num:nth-child(5) {
            transform: rotate(240deg);
        }

        .clock .dial .num:nth-child(6) {
            transform: rotate(270deg);
        }

        .clock .dial .num:nth-child(7) {
            transform: rotate(300deg);
        }

        .clock .dial .num:nth-child(8) {
            transform: rotate(330deg);
        }

        .clock .dial .num:nth-child(9) {
            transform: rotate(360deg);
        }

        .clock .dial .num:nth-child(10) {
            transform: rotate(30deg);
        }

        .clock .dial .num:nth-child(11) {
            transform: rotate(60deg);
        }

        .clock .dial .num:nth-child(12) {
            transform: rotate(90deg);
        }

经过上面定位之后数字已经放置在正确的位置了,但数字本身看着挺难受的,这里只要对数字本身再进行一次反方向的旋转即可:

在这里插入图片描述

上面部分代码如下:

        /* 数字文本角度调整 */
        .clock .dial .num span {
            display: inline-block;
            font-size: 2rem;
        }

        .clock .dial .num:nth-child(1) span {
            transform: rotate(-120deg);
        }

        .clock .dial .num:nth-child(2) span {
            transform: rotate(-150deg);
        }

        .clock .dial .num:nth-child(3) span {
            transform: rotate(-180deg);
        }

        .clock .dial .num:nth-child(4) span {
            transform: rotate(-210deg);
        }

        .clock .dial .num:nth-child(5) span {
            transform: rotate(-240deg);
        }

        .clock .dial .num:nth-child(6) span {
            transform: rotate(-270deg);
        }

        .clock .dial .num:nth-child(7) span {
            transform: rotate(-300deg);
        }

        .clock .dial .num:nth-child(8) span {
            transform: rotate(-330deg);
        }

        .clock .dial .num:nth-child(9) span {
            transform: rotate(-360deg);
        }

        .clock .dial .num:nth-child(10) span {
            transform: rotate(-30deg);
        }

        .clock .dial .num:nth-child(11) span {
            transform: rotate(-60deg);
        }

        .clock .dial .num:nth-child(12) span {
            transform: rotate(-90deg);
        }

指针定位

指针的定位和前面数字部分定位差不多,依赖于绝对定位:

在这里插入图片描述

上面演示中可以看到我将指针区域平分成两部分,一部分涂黑显示,这样就看到了从表盘中间延申出来的指针。上面部分新增代码如下:

        /* 表针样式 */
        .clock .dial .hand {
            position: absolute;
            display: grid;
            grid-template-rows: 1fr 1fr;
        }

        .clock .dial .hand span:nth-child(1) {
            background-color: black;
        }

        .clock .dial .hand.hour {
            width: 4%;
            height: 40%;
        }

        .clock .dial .hand.minute {
            width: 2%;
            height: 60%;
        }

        .clock .dial .hand.second {
            width: 1%;
            height: 80%;
        }

指针运转

指针有了之后我们当然最希望看到指针可以随着时间流逝旋转起来。指针的旋转运动在这里主要是改变其布局的角度就行。下面是个简单的演示:

在这里插入图片描述

上面演示中我每秒读取一次当前时间,并根据时间来计算表针位置并更新。脚本部分代码如下:

    <!-- 指针转动脚本 -->
    <script>
        var handhour = document.getElementById("handhour");
        var handmin = document.getElementById("handmin");
        var handsec = document.getElementById("handsec");

        function change() {
            var time = new Date();
            handhour.style.transform = "rotate(" + ((time.getHours() % 12) * 30 + time.getMinutes() * 6 / 12) + "deg)";
            handmin.style.transform = "rotate(" + time.getMinutes() * 6 + "deg)";
            handsec.style.transform = "rotate(" + time.getSeconds() * 6 + "deg)"
        }

        change(); // 指针初次定位

        setInterval(change, 1000); // 指针每秒转动一次
    </script>

完整代码

对上面的所有内容进行整合,稍加调整就可以实现文章开头的效果了,完整代码如下:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        body {
            width: 100vw;
            height: 100vh;
            display: grid;
            place-items: center;
            background-color: lightgray;
            user-select: none;
        }

        /* 时钟基本样式 */
        .clock {
            width: 400px;
            height: 400px;
            border-radius: 50%;
            background-color: white;
            display: grid;
            place-items: center;
        }

        /* 时钟表盘样式 */
        .clock .dial {
            width: 90%;
            height: 90%;
            border-radius: 50%;
            display: grid;
            place-items: center;
            /* 与下面position: absolute;配合使用,使下面元素都以本容器为父容器进行绝对定位 */
            position: relative;
        }

        /* 中心点样式 */
        .clock .dial .point {
            position: absolute;
            width: 8%;
            height: 8%;
            border-radius: 50%;
            background-color: black;
        }

        /* 表针样式 */
        .clock .dial .hand {
            position: absolute;
            display: grid;
            grid-template-rows: 1fr 1fr;
        }

        .clock .dial .hand span:nth-child(1) {
            background-color: black;
        }

        .clock .dial .hand.hour {
            width: 4%;
            height: 40%;
        }

        .clock .dial .hand.minute {
            width: 2%;
            height: 60%;
        }

        .clock .dial .hand.second {
            width: 1%;
            height: 80%;
        }

        /* 数字区域定位 */
        .clock .dial .num {
            position: absolute;
            width: 100%;
        }

        .clock .dial .num:nth-child(1) {
            transform: rotate(120deg);
        }

        .clock .dial .num:nth-child(2) {
            transform: rotate(150deg);
        }

        .clock .dial .num:nth-child(3) {
            transform: rotate(180deg);
        }

        .clock .dial .num:nth-child(4) {
            transform: rotate(210deg);
        }

        .clock .dial .num:nth-child(5) {
            transform: rotate(240deg);
        }

        .clock .dial .num:nth-child(6) {
            transform: rotate(270deg);
        }

        .clock .dial .num:nth-child(7) {
            transform: rotate(300deg);
        }

        .clock .dial .num:nth-child(8) {
            transform: rotate(330deg);
        }

        .clock .dial .num:nth-child(9) {
            transform: rotate(360deg);
        }

        .clock .dial .num:nth-child(10) {
            transform: rotate(30deg);
        }

        .clock .dial .num:nth-child(11) {
            transform: rotate(60deg);
        }

        .clock .dial .num:nth-child(12) {
            transform: rotate(90deg);
        }

        /* 数字文本角度调整 */
        .clock .dial .num span {
            display: inline-block;
            font-size: 2rem;
        }

        .clock .dial .num:nth-child(1) span {
            transform: rotate(-120deg);
        }

        .clock .dial .num:nth-child(2) span {
            transform: rotate(-150deg);
        }

        .clock .dial .num:nth-child(3) span {
            transform: rotate(-180deg);
        }

        .clock .dial .num:nth-child(4) span {
            transform: rotate(-210deg);
        }

        .clock .dial .num:nth-child(5) span {
            transform: rotate(-240deg);
        }

        .clock .dial .num:nth-child(6) span {
            transform: rotate(-270deg);
        }

        .clock .dial .num:nth-child(7) span {
            transform: rotate(-300deg);
        }

        .clock .dial .num:nth-child(8) span {
            transform: rotate(-330deg);
        }

        .clock .dial .num:nth-child(9) span {
            transform: rotate(-360deg);
        }

        .clock .dial .num:nth-child(10) span {
            transform: rotate(-30deg);
        }

        .clock .dial .num:nth-child(11) span {
            transform: rotate(-60deg);
        }

        .clock .dial .num:nth-child(12) span {
            transform: rotate(-90deg);
        }
    </style>
</head>

<body>
    <div class="clock">
        <div class="dial">
            <div class="num"><span>1</span></div>
            <div class="num"><span>2</span></div>
            <div class="num"><span>3</span></div>
            <div class="num"><span>4</span></div>
            <div class="num"><span>5</span></div>
            <div class="num"><span>6</span></div>
            <div class="num"><span>7</span></div>
            <div class="num"><span>8</span></div>
            <div class="num"><span>9</span></div>
            <div class="num"><span>10</span></div>
            <div class="num"><span>11</span></div>
            <div class="num"><span>12</span></div>
            <div class="point"></div>
            <div class="hand hour" id="handhour"><span></span><span></span></div>
            <div class="hand minute" id="handmin"><span></span><span></span></div>
            <div class="hand second" id="handsec"><span></span><span></span></div>
        </div>
    </div>

    <!-- 指针转动脚本 -->
    <script>
        var handhour = document.getElementById("handhour");
        var handmin = document.getElementById("handmin");
        var handsec = document.getElementById("handsec");

        function change() {
            var time = new Date();
            handhour.style.transform = "rotate(" + ((time.getHours() % 12) * 30 + time.getMinutes() * 6 / 12) + "deg)";
            handmin.style.transform = "rotate(" + time.getMinutes() * 6 + "deg)";
            handsec.style.transform = "rotate(" + time.getSeconds() * 6 + "deg)"
        }

        change(); // 指针初次定位

        setInterval(change, 1000); // 指针每秒转动一次
    </script>
</body>

</html>

总结

圆形表盘时钟布局从代码上来说其实并不难,主要是考验空间想象能力。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naisu Xu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值