css 制作简单的时钟

1,472 阅读4分钟

1 前言

用css和js实现一个时钟,再加上切换时区。

2 制作思路

  1. 画表盘
  2. 添加时针,分针,秒针
  3. 设置指针
  4. 设置时区

3 代码实现

画表盘

先实现一个表盘的表框,

#title {
    width: 200px;
    font-size: 30px;
    text-align: center;
    color: aquamarine;
    margin: 100px auto 10px;
}

#box {
    width: 200px;
    height: 200px;
    position: relative;
    border-radius: 50%;
    border: 5px solid black;
    margin: 0 auto;
}

#scale {
    width: 200px;
    height: 200px;
    position: absolute;
}

#scale div {
    width: 20px;
    height: 200px;
    position: absolute;
    left: 92px;
}

再把数字添加到表盘中

<div id="scale">
    <div><span>12</span></div>
    <div><span>1</span></div>
    <div><span>2</span></div>
    <div><span>3</span></div>
    <div><span>4</span></div>
    <div><span>5</span></div>
    <div><span>6</span></div>
    <div><span>7</span></div>
    <div><span>8</span></div>
    <div><span>9</span></div>
    <div><span>10</span></div>
    <div><span>11</span></div>
</div>

现在的效果是有一个黑色圆框,数字都叠在了一起。如图:

image.png

用css一个一个改变位置太麻烦了,可以用js获取所有节点,遍历改变角度,如图:

for (let i = 0; i < scaleDivs.length; i++) {
    //表盘一圈360度,总共有12个刻度,每个刻度之间是360/12=30度
    scaleDivs[i].style.transform = "rotate(" + i * 30 + "deg)";
}

image.png

但是刻度值有正反向问题,里面的span在反转回去,如图

//解决刻度值显示正向问题,反向转回去就可以了
scaleDivs[i].firstChild.style.transform = "rotate(" + -i * 30 + "deg)";

image.png

添加时针,分针,秒针

添加表针这个属性可以记一下transform-origin,这个属性可以改变中心点,因为指针是有一个中心点,我们把指针的中心点设置在底部中间的位置。

#hour {
    width: 4px;
    height: 50px;
    position: absolute;
    background-color: red;
    left: 97px;
    top: 50px;
    /*这个属性可以改变旋转的中心点*/
    transform-origin: bottom center;
}

#minute {
    width: 4px;
    height: 70px;
    position: absolute;
    background-color: cyan;
    left: 97px;
    top: 30px;
    /*这个属性可以改变旋转的中心点*/
    transform-origin: bottom center;
}

#second {
    width: 4px;
    height: 90px;
    position: absolute;
    background-color: pink;
    left: 97px;
    top: 10px;
    /*这个属性可以改变旋转的中心点*/
    transform-origin: bottom center;
}
<div id="hour"></div>
<div id="minute"></div>
<div id="second"></div>

效果如图:

image.png

设置指针

  • 秒针:一圈360度,一圈60秒,每秒是360/60=6度
  • 分针:一圈360度,一圈60分,每分是360/60=6度
  • 时针:一圈360度,一圈12小时,每秒是360/12=30度

按照上面的想法,在给个定时器是不是就动起来

//获取时分秒针DIV
var hourDiv = document.querySelector("#hour");
var minuteDiv = document.querySelector("#minute");
var secondDiv = document.querySelector("#second");

//获取时分秒
var date = new Date();
//把小时转换成12进制,方便运算
var hour = date.getHours() % 12;

var minute = date.getMinutes();

var second = date.getSeconds();

//设置指针
function setPointers() {
    second++;
    if (second == 60) {
        second = 0;
        minute++;
        if (minute == 60) {
            minute = 0;
            hour++;
            if (hour == 13) {
                hour = 0;
            }
        }
    }

    //一圈360度,一圈60秒,每秒是360/60=6secondDiv.style.transform = "rotate(" + second * 6 + "deg)";
    //一圈360度,一圈60分,每分是360/60=6minuteDiv.style.transform = "rotate(" + minute * 6 + "deg)";
    //一圈360度,一圈12小时,每秒是360/12=30度
    //一小时是30度,一小时是60分钟,一分钟是30/60=0.5hourDiv.style.transform = "rotate(" + (hour * 30 + minute * 0.5) + "deg)";

}
setPointers();
//创建定时器
setInterval(function  () {
    setPointers();
},1000);

效果如图:

myxdi-2f8d8.gif

这里我为了指针和刻度能够对齐,给1位数字的刻度加了点样式,以12数字的宽度为基础,然后居中

#box div:nth-of-type(2) span,
#box div:nth-of-type(3) span,
#box div:nth-of-type(4) span,
#box div:nth-of-type(5) span,
#box div:nth-of-type(6) span,
#box div:nth-of-type(7) span,
#box div:nth-of-type(8) span,
#box div:nth-of-type(9) span,
#box div:nth-of-type(10) span{
    width: 20px;
    text-align: center;
}

设置时区

世界这么多的时区,得有一个标准,就是GMT,格林尼治时间

百度百科:世界时UT [1]  即格林尼治 [1]  平太阳时间,是指格林尼治所在地的标准时间,也是表示地球自转速率的一种形式。

添加select,选择时区

<div id="select_box">
    <label>
        <select onchange="onChangeTimeFunc(value)">
            <!--东区时间-->
            <option value="0">零时区</option>
            <option value="1">东一区</option>
            <option value="2">东二区</option>
            <option value="3">东三区</option>
            <option value="4">东四区</option>
            <option value="5">东五区</option>
            <option value="6">东六区</option>
            <option value="7">东七区</option>
            <option value="8" selected="selected">东八区</option>
            <option value="9">东九区</option>
            <option value="10">东十区</option>
            <option value="12">东十二区</option>
            <!--西区时间-->
            <option value="-10">西十区</option>
            <option value="-9">西九区</option>
            <option value="-8">西八区</option>
            <option value="-7">西七区</option>
            <option value="-6">西六区</option>
            <option value="-5">西五区</option>
            <option value="-4">西四区</option>
            <option value="-3">西三区</option>
        </select>
    </label>
</div>

选择时区处理函数

// 选择时区的时间
function onChangeTimeFunc(value) {
    clearInterval(timer);
    // 获取当前时区时间
    const date = getLocalTime(Number(value));
    // 设置指针
    setPointers(date);
    // 启动定时器
    timer = setInterval(function () {
        // 每次获取当前时区时间
        const currentDate = getLocalTime(Number(value));
        setPointers(currentDate);
    }, 1000);
}

获取选择的时区的当前时间

//得到标准时区的时间的函数
function getLocalTime(i) {
    //参数i为时区值数字,比如北京为东八区则输进8,西八区则输入-8
    const d = new Date();
    //得到1970年一月一日到现在的秒数
    const len = d.getTime();
    //本地时间与GMT时间的时间偏移差
    const offset = d.getTimezoneOffset() * 60000;
    //得到现在的格林尼治时间
    const utcTime = len + offset;
    return new Date(utcTime + 3600000 * i);
}

需要再把之前写的setPointers方法重新封装一下,时间就不能用当前时间,要用传入的参数

//设置指针
function setPointers(date) {
    //把小时转换成12进制,方便运算
    let hour = date.getHours() % 12;

    let minute = date.getMinutes();

    let second = date.getSeconds();

    second++;
    if (second === 60) {
        second = 0;
        minute++;
        if (minute === 60) {
            minute = 0;
            hour++;
            if (hour === 13) {
                hour = 0;
            }
        }
    }

    //一圈360度,一圈60秒,每秒是360/60=6secondDiv.style.transform = "rotate(" + second * 6 + "deg)";
    //一圈360度,一圈60分,每分是360/60=6minuteDiv.style.transform = "rotate(" + minute * 6 + "deg)";
    //一圈360度,一圈12小时,每秒是360/12=30度
    //一小时是30度,一小时是60分钟,一分钟是30/60=0.5hourDiv.style.transform = "rotate(" + (hour * 30 + minute * 0.5) + "deg)";
}

默认调用东八区北京时间

// 默认选中北京-东八区时间
onChangeTimeFunc(8);

效果如图

7aadp-r7g0o.gif

最后美化了一下,添加一个title,显示一个数码方式时钟,效果如图:

myg3h-0rpor.gif

4 完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        * {
            padding: 0;
            margin: 0;
        }

        #title {
            width: 200px;
            font-size: 30px;
            text-align: center;
            color: aquamarine;
            margin: 100px auto 10px;
        }

        #box {
            width: 200px;
            height: 200px;
            position: relative;
            border-radius: 50%;
            border: 5px solid black;
            margin: 0 auto;
        }

        #scale {
            width: 200px;
            height: 200px;
            position: absolute;
        }

        #scale div {
            width: 20px;
            height: 200px;
            position: absolute;
            left: 92px;
        }

        #box span {
            display: block;
            position: absolute;
        }

        #box div:nth-of-type(2) span,
        #box div:nth-of-type(3) span,
        #box div:nth-of-type(4) span,
        #box div:nth-of-type(5) span,
        #box div:nth-of-type(6) span,
        #box div:nth-of-type(7) span,
        #box div:nth-of-type(8) span,
        #box div:nth-of-type(9) span,
        #box div:nth-of-type(10) span{
            width: 20px;
            text-align: center;
        }

        #hour {
            width: 4px;
            height: 50px;
            position: absolute;
            background-color: red;
            left: 97px;
            top: 50px;
            /*这个属性可以改变旋转的中心点*/
            transform-origin: bottom center;
        }

        #minute {
            width: 4px;
            height: 70px;
            position: absolute;
            background-color: cyan;
            left: 97px;
            top: 30px;
            /*这个属性可以改变旋转的中心点*/
            transform-origin: bottom center;
        }

        #second {
            width: 4px;
            height: 90px;
            position: absolute;
            background-color: pink;
            left: 97px;
            top: 10px;
            /*这个属性可以改变旋转的中心点*/
            transform-origin: bottom center;
        }

        #current_time_box, #select_box {
            width: 200px;
            margin: 0 auto;
        }

        #current_time_box {
            padding: 20px 0;
            text-align: center;
        }

        #current_time_box span {
            height: 22px;
        }

        #select_box select{
            width: 100%;
            height: 30px;
        }
    </style>
</head>
<body>
<div id="title">
    世界名表
</div>
<div id="box">
    <div id="scale">
        <div><span>12</span></div>
        <div><span>1</span></div>
        <div><span>2</span></div>
        <div><span>3</span></div>
        <div><span>4</span></div>
        <div><span>5</span></div>
        <div><span>6</span></div>
        <div><span>7</span></div>
        <div><span>8</span></div>
        <div><span>9</span></div>
        <div><span>10</span></div>
        <div><span>11</span></div>
    </div>
    <div id="hour"></div>
    <div id="minute"></div>
    <div id="second"></div>
</div>
<div id="current_time_box">
    <span id="current_time">--</span>
</div>
<div id="select_box">
    <label>
        <select onchange="onChangeTimeFunc(value)">
            <!--东区时间-->
            <option value="0">零时区</option>
            <option value="1">东一区</option>
            <option value="2">东二区</option>
            <option value="3">东三区</option>
            <option value="4">东四区</option>
            <option value="5">东五区</option>
            <option value="6">东六区</option>
            <option value="7">东七区</option>
            <option value="8" selected="selected">东八区</option>
            <option value="9">东九区</option>
            <option value="10">东十区</option>
            <option value="12">东十二区</option>
            <!--西区时间-->
            <option value="-10">西十区</option>
            <option value="-9">西九区</option>
            <option value="-8">西八区</option>
            <option value="-7">西七区</option>
            <option value="-6">西六区</option>
            <option value="-5">西五区</option>
            <option value="-4">西四区</option>
            <option value="-3">西三区</option>
        </select>
    </label>
</div>
<script src="https://unpkg.com/dayjs"></script>
<script type="text/javascript">
    const scaleDivs = document.querySelectorAll("#scale div");
    // 定时器
    let timer = null;
    //循环控制刻度形变的角度
    for (let i = 0; i < scaleDivs.length; i++) {
        //表盘一圈360度,总共有12个刻度,每个刻度之间是360/12=30度
        scaleDivs[i].style.transform = "rotate(" + i * 30 + "deg)";
        //解决刻度值显示正向问题,反向转回去就可以了
        scaleDivs[i].firstChild.style.transform = "rotate(" + -i * 30 + "deg)";
    }

    //获取时分秒针DIV
    const hourDiv = document.querySelector("#hour");
    const minuteDiv = document.querySelector("#minute");
    const secondDiv = document.querySelector("#second");
    // 获取文本显示span
    const currentTimeSpan = document.querySelector("#current_time");

    // 选择时区的时间
    function onChangeTimeFunc(value) {
        clearInterval(timer);
        currentTimeSpan.innerHTML = '';
        // 获取当前时区时间
        const date = getLocalTime(Number(value));
        // 设置指针
        setPointers(date);
        // 启动定时器
        timer = setInterval(function () {
            // 每次获取当前时区时间
            const currentDate = getLocalTime(Number(value));
            setPointers(currentDate);
        }, 1000);
    }

    //得到标准时区的时间的函数
    function getLocalTime(i) {
        //参数i为时区值数字,比如北京为东八区则输进8,西八区则输入-8
        const d = new Date();
        //得到1970年一月一日到现在的秒数
        const len = d.getTime();
        //本地时间与GMT时间的时间偏移差
        const offset = d.getTimezoneOffset() * 60000;
        //得到现在的格林尼治时间
        const utcTime = len + offset;
        return new Date(utcTime + 3600000 * i);
    }

    //设置指针
    function setPointers(date) {
        //把小时转换成12进制,方便运算
        let hour = date.getHours() % 12;

        let minute = date.getMinutes();

        let second = date.getSeconds();

        second++;
        if (second === 60) {
            second = 0;
            minute++;
            if (minute === 60) {
                minute = 0;
                hour++;
                if (hour === 13) {
                    hour = 0;
                }
            }
        }

        //一圈360度,一圈60秒,每秒是360/60=6度
        secondDiv.style.transform = "rotate(" + second * 6 + "deg)";
        //一圈360度,一圈60分,每分是360/60=6度
        minuteDiv.style.transform = "rotate(" + minute * 6 + "deg)";
        //一圈360度,一圈12小时,每秒是360/12=30度
        //一小时是30度,一小时是60分钟,一分钟是30/60=0.5度
        hourDiv.style.transform = "rotate(" + (hour * 30 + minute * 0.5) + "deg)";
        // 赋值span
        currentTimeSpan.innerHTML =  dayjs(date).format('YYYY-MM-DD HH:mm:ss');
    }

    // 默认选中北京-东八区时间
    onChangeTimeFunc(8);
</script>
</body>
</html>

最后

今天是平安夜,希望大家平安快乐!

各位,早点下班,顺便留下你的脚印,谢谢