前端例程 002:圆形表盘时钟布局

Posted Naisu Xu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端例程 002:圆形表盘时钟布局相关的知识,希望对你有一定的参考价值。

目的

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

布局说明

基础准备

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

<!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">以上是关于前端例程 002:圆形表盘时钟布局的主要内容,如果未能解决你的问题,请参考以下文章

H5之canvas-绘制动态时钟

自定义UI 自制表盘

自定义UI 自制表盘

Android Wear 圆形模拟器充气方形布局

51nod 1282 时钟

java实现时钟表盘教程方法