CSS+JS实现一个轮盘时钟

null

Posted by NeptLiang on August 9, 2020

0x00 前言

/* 之前学校计算机社团招新前叫我收集理事们的技术作品来展示,结果只有一位理事交了份作品,我又刚好在网上看到一个安卓的什么“抖X网红时钟动态壁纸”,就试着用CSS和JS整了一个类似的交了上去。所幸最后另一位理事交了第二份作品,用不上我这个

截图

该玩意纯为本菜鸡练习之作,请各路巨佬勿嘲

完整源码:github.com/NEPTLIANG/Web/tree/master/RotateClock/RotateClock_v1.0(v2.0~v4.0都是待修改的半成品) */


0x01 HTML搭个框

先大致整几个div,文字之类的一条条写的话比较繁琐,故用JS生成:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="RotateClock.css" rel="stylesheet"/>  <!--引入样式-->
</head>
<body>
<div class="father">  <!--父布局,用来调整整体位置-->
    <div id="time" class="time"></div>  <!--中间的时间-->
    <div id="date" class="date"></div>  <!--中间的日期-->
    <div id="wheelOfSeconds" class="wheel"></div>  <!--显示秒的轮-->
    <div id="wheelOfMinutes" class="wheel"></div>  <!--显示分钟的轮-->
    <div id="wheelOfHours" class="wheel"></div>  <!--显示小时的轮-->
</div>
<script src="RotateClock.js"></script>  <!--引入JS-->
</body>
</html>

框


0x02 样式整上

设置一下背景字体什么的:

body {
    background: #000;
    color: #00ffff;
    text-shadow: rgba(0, 255, 255, 50) 0 0 1em;
    font-size: 32px;
}

背景字体

给父div整个绝对定位

.father {
    position: absolute;
}

因为显示秒的轮的旋转基点(圆心)设置在x轴的-1024px,所以旋转半径为1024px,把轮盘右移1024px,以便让定位锚点从右边第一行字的左上角移到圆心,设置每60秒旋转一周:

#wheelOfSeconds {
    left: 1024px;  /*右移*/
    position: absolute;
    display: inline;
    transform-origin: -1024px;  /*设置圆心*/
    animation: rotate 60s infinite linear;  /*应用后面设置的旋转关键帧rotate*/
}

显示分钟的轮的旋转半径为768px,把轮盘左移1024px,每3600秒旋转一周:

#wheelOfMinutes {
    left: 768px;  /*右移*/
    position: absolute;
    display: inline;
    transform-origin: -768px;  /*设置圆心*/
    animation: rotate 3600s infinite linear;  /*旋转*/
}

显示小时的轮的旋转半径为512px,每24小时旋转一周:

#wheelOfHours {
    left: 512px;  /*右移*/
    position: absolute;
    display: inline;
    transform-origin: -512px;  /*设置圆心*/
    animation: rotate 86400s infinite linear;  /*旋转*/
}

设置轮盘中间的时间和日期样式:

#time {
    font-size: 128px;
    position: relative;
    left: -50%;
    top: 128px;
}

#date {
    font-size: 48px;
    position: relative;
    left: -50%;
    top: 128px;
    text-align: center;
}

设置轮盘上文字的样式:

.seconds {  /*显示秒的轮盘上的文字*/
    transform-origin: -1024px;  /*旋转半径1024px*/
    position: fixed;
    width: 256px;
}

.minutes {  /*显示分钟的轮盘上的文字*/
    transform-origin: -768px;  /*旋转半径768px*/
    position: fixed;
    width: 256px;
}

.hours {  /*显示小时的轮盘上的文字*/
    transform-origin: -512px;
    position: fixed;
    width: 256px;
}

设置旋转关键帧rotate为逆时针旋转360°:

@keyframes rotate {
    100% {
        transform: rotate(-360deg);
    }
}

0x03 完成JS

先是两个后面用到的参数,由于调整起来效果不好,就不详述了,保持默认即可,或者可以自己尝试调整一下:

var rotate = 0;  //设置轮盘3D旋转角度
var left = -50 + "%";  //设置中间日期位置偏移,默认-50%

实现父div居中

var height = window.innerHeight;
var father = document.getElementsByClassName("father");
father[0].style.left = "50%";
father[0].style.top = (height / 2 - 204).toString() + "px";

居中

生成轮盘,轮盘上的文字一条条写太麻烦了,所以用JS生成一下(虽然也方便不了多少,但好歹不用一条条写)。先做一些准备工作:

var num = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""];
var num2 = ["", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "", "", "",];
var wheelOfSeconds = document.getElementById("wheelOfSeconds");
var wheelOfMinutes = document.getElementById("wheelOfMinutes");
var wheelOfHours = document.getElementById("wheelOfHours");
var hours = [], minutes = [], seconds = [];
var i;
var initTime = new Date();  //获取当前日期时间,作为轮盘最右边的初始时间
var initSecond = initTime.getSeconds();
var initMinute = initTime.getMinutes() + initSecond / 60;
var initHour = initTime.getHours() + initMinute / 60;

然后拼接秒和分钟文字并插到轮盘div里

for (i = 0; i < 60; i++) {
    seconds.push(document.createElement("div"));
    minutes.push(document.createElement("div"));
    if (i === 0) {
        seconds[i].innerHTML = "";
        minutes[i].innerHTML = "零分";
    }
    if (i > 0 && i <= 10) {
        seconds[i].innerHTML = "" + num[i] + "";
        minutes[i].innerHTML = "" + num[i] + "";
    }
    if (i >= 10 && i < 20) {
        seconds[i].innerHTML = num2[i % 10] + "";
        minutes[i].innerHTML = num2[i % 10] + "";
    }
    if (i >= 20 && i < 60) {
        seconds[i].innerHTML = num[Math.floor(i / 10)] + num2[i % 10] + "";
        minutes[i].innerHTML = num[Math.floor(i / 10)] + num2[i % 10] + "";
    }
    seconds[i].className = "seconds";  //设置秒的文字样式
    minutes[i].className = "minutes";  //设置分钟文字样式
    seconds[i].style = "transform: rotate(" + 6 * (i - initSecond) + "deg);";  //设置秒的文字旋转角度,组成轮盘
    minutes[i].style = "transform: rotate(" + 6 * (i - initMinute) + "deg);";  //设置分钟文字旋转角度,组成轮盘
    wheelOfSeconds.appendChild(seconds[i]);
    wheelOfMinutes.appendChild(minutes[i]);
}

分钟和秒

再拼接小时文字并插到轮盘div里

for (i = 0; i < 24; i++) {
    hours.push(document.createElement("div"));
    if (i === 0) {
        hours[i].innerHTML = "零时";
    }
    if (i > 0 && i <= 10) {
        hours[i].innerHTML = num[i] + "";
    }
    if (i >= 10 && i < 20) {
        hours[i].innerHTML = num2[i % 10] + "";
    }
    if (i >= 20 && i < 24) {
        hours[i].innerHTML = num[Math.floor(i / 10)] + num2[i % 10] + "";
    }
    hours[i].className = "hours";  //设置小时文字样式
    hours[i].style = "transform: rotate(" + 15 * (i - initHour) + "deg);";  //设置小时文字旋转角度,组成轮盘
    wheelOfHours.appendChild(hours[i]);
}

小时

整一个函数来更新时间文字样式

var date, year, month, day, hour, minute, second;
var time = document.getElementById("time");
var dateDiv = document.getElementById("date");
function changeStyle() {
    date = new Date();  //获取当前时间
    year = date.getFullYear();
    month = date.getMonth() + 1;
    day = date.getDate();
    hour = date.getHours();
    minute = date.getMinutes();
    second = date.getSeconds();
    time.innerHTML = hour.toString() + ":" + minute.toString();
    dateDiv.innerHTML = year + "." + month.toString() + "." + day.toString();  //设置轮盘中间的日期
    hours[hour].style.color = "#fff";  //设置轮盘上当前小时的文字样式
    hours[hour].style.textShadow = "rgba(255, 255, 255, 50) 0 0 1em";
    hours[(hour + 24 - 1) % 24].style.color = "#0ff";  //恢复上一小时的文字样式
    hours[(hour + 24 - 1) % 24].style.color = "rgba(0, 255, 255, 50) 0 0 1em";
    minutes[minute].style.color = "#fff";  //设置轮盘上当前分钟的文字样式
    minutes[minute].style.textShadow = "rgba(255, 255, 255, 100) 0 0 1em";
    minutes[(minute + 60 - 1) % 60].style.color = "#0ff";  //恢复上一分钟的文字样式
    minutes[(minute + 60 - 1) % 60].style.color = "rgba(0, 255, 255, 50) 0 0 1em";
    seconds[second].style.color = "#fff";  //设置轮盘上当前秒的文字样式
    seconds[second].style.textShadow = "rgba(255, 255, 255, 50) 0 0 1em";
    seconds[(second + 60 - 1) % 60].style.color = "#0ff";  //恢复上一秒的文字样式
    seconds[(second + 60 - 1) % 60].style.color = "rgba(0, 255, 255, 50) 0 0 1em";
}

设置轮盘3D旋转,这一小段可有可无。就是这里用到了JS部分开头那两个参数,由于实现起来效果不好,所以旋转角度默认设成0:

father[0].style.transform = `rotate3d(-1, 1, 0, ${rotate}deg)`;
time.style.transform = `rotate3d(1, 1, 0, ${rotate}deg)`;
dateDiv.style.transform = `rotate3d(1, 1, 0, ${rotate}deg)`;
dateDiv.style.left = left;

最后设置每0.1秒更新一次轮盘上的文字样式:

setInterval(changeStyle, 100);

更新

就完事了

//End of article

参考文献

公众号二维码