马黑黑 发表于 2022-3-20 10:57

让CSS驱动我们的数字盘时钟

本帖最后由 马黑黑 于 2022-3-20 13:57 编辑 <br /><br /><style type="text/css">

.numClock {
        margin: auto;
        width: 20em;
        height: 20em;
        background: rgba(240, 248, 255, .6);
        border: 1.2em solid #2f4f4f;
        border-radius: 50%;
        position: relative;
}
.numClock::before {
        content: "CHUACHAO";
        position: absolute;
        width: 100%;
        text-align: center;
        top: 70%;
}
.numBox {
        position: absolute;
        width: 1.5em;
        height: 1.5em;
        font-family: 'Microsoft Yahei', Sans-Seri;
        font-size: 1.5em;
        left: calc(50% - 0.75em);
        top: calc(50% - 0.75em);
        background: transparent;
        text-align:center;
}

.numBox span { display: inline-block; }

.hHand,.mHand,.sHand { position: absolute; width: 100%; height: 100%; background: transparent;}

.hr-hand, .min-hand,.sec-hand {
        position: absolute;
        bottom: 50%;
        transform-origin: 50% 100%;
}

.hr-hand {
        background: #2f4f4f;
        width: 0.4em;
        height: 30%;
        left: calc(50% - 0.2em);
        animation: tRun 43200s linear infinite;
}

.hr-hand::after {
        content: "";
        position: absolute;
        width: 0; height: 0;
        border: 0.5em solid;
        border-color: transparent transparent #2f4f4f transparent;
        right: -0.3em;
        bottom: 100%;
}

.min-hand {
        background: #2f4f4f;
        width: 0.3em;
        height: 42%;
        left: calc(50% - 0.15em);
        animation: tRun 3600s linear infinite;
}

.sec-hand {
        background: #d00;
        width: 0.2em;
        height: 48%;
        left: calc(50% - 0.1em);
        border-radius: 60% 60% 20% 20%;
        animation: tRun 60s linear infinite;
}

.sec-hand::before {
        content: "";
        position: absolute;
        bottom: -0.3em;
        left: -0.3em;
        width: 0.8em;
        height: 0.8em;
        border-radius: 50%;
        background: red;
}

@keyframes tRun { to { transform: rotate(1turn);} }

</style>

<div class="numClock">
        <div class="hHand">
                <div class="hr-hand"></div>
        </div>
        <div class="mHand">
                <div class="min-hand"></div>
        </div>
        <div class="sHand">
                <div class="sec-hand"></div>
        </div>
</div>

<script language="javascript">

addNum();

function addNum() {
        var nStr = "";
        for(j=0;j<12;j++) {
                nStr += "<div class='numBox' style='transform: rotate(" + j*30 + "deg) translateY(-5.8em);'><span style='transform: rotate(-" + j*30 + "deg);'>" + (j == 0 ? "12" : j) + "</span></div>";
        }
        document.querySelector(".numClock").innerHTML = nStr + document.querySelector(".numClock").innerHTML;
}

</script>

马黑黑 发表于 2022-3-20 10:59

本帖最后由 马黑黑 于 2022-3-20 13:57 编辑

全部代码:

<style type="text/css">

.numClock {
      margin: auto;
      width: 20em;
      height: 20em;
      background: rgba(240, 248, 255, .6);
      border: 1.2em solid #2f4f4f;
      border-radius: 50%;
      position: relative;
}
.numClock::before {
      content: "CHUACHAO";
      position: absolute;
      width: 100%;
      text-align: center;
      top: 70%;
}
.numBox {
      position: absolute;
      width: 1.5em;
      height: 1.5em;
      font-family: 'Microsoft Yahei', Sans-Seri;
      font-size: 1.5em;
      left: calc(50% - 0.75em);
      top: calc(50% - 0.75em);
      background: transparent;
      text-align:center;
}

.numBox span { display: inline-block; }

.hHand,.mHand,.sHand { position: absolute; width: 100%; height: 100%; background: transparent;}

.hr-hand, .min-hand,.sec-hand {
      position: absolute;
      bottom: 50%;
      transform-origin: 50% 100%;
}

.hr-hand {
      background: #2f4f4f;
      width: 0.4em;
      height: 30%;
      left: calc(50% - 0.2em);
      animation: tRun 43200s linear infinite;
}

.hr-hand::after {
      content: "";
      position: absolute;
      width: 0; height: 0;
      border: 0.5em solid;
      border-color: transparent transparent #2f4f4f transparent;
      right: -0.3em;
      bottom: 100%;
}

.min-hand {
      background: #2f4f4f;
      width: 0.3em;
      height: 42%;
      left: calc(50% - 0.15em);
      animation: tRun 3600s linear infinite;
}

.sec-hand {
      background: #d00;
      width: 0.2em;
      height: 48%;
      left: calc(50% - 0.1em);
      border-radius: 60% 60% 20% 20%;
      animation: tRun 60s linear infinite;
}

.sec-hand::before {
      content: "";
      position: absolute;
      bottom: -0.3em;
      left: -0.3em;
      width: 0.8em;
      height: 0.8em;
      border-radius: 50%;
      background: red;
}

@keyframes tRun { to { transform: rotate(1turn);} }

</style>

<div class="numClock">
      <div class="hHand">
                <div class="hr-hand"></div>
      </div>
      <div class="mHand">
                <div class="min-hand"></div>
      </div>
      <div class="sHand">
                <div class="sec-hand"></div>
      </div>
</div>

<script language="javascript">

addNum();

function addNum() {
      var nStr = "";
      for(j=0;j<12;j++) {
                nStr += "<div class='numBox' style='transform: rotate(" + j*30 + "deg) translateY(-5.8em);'><span style='transform: rotate(-" + j*30 + "deg);'>" + (j == 0 ? "12" : j) + "</span></div>";
      }
      document.querySelector(".numClock").innerHTML = nStr + document.querySelector(".numClock").innerHTML;
}

</script>

马黑黑 发表于 2022-3-20 11:04

时钟的指针运转了,但是时间不对,没关系,我们将在下一步通过JS来完成校时。JS仅做首次校时之用,然后一切都将由CSS的动画提供持续不断的动力——这是一个永动机效果的石英钟,它真正运行之后就无需加电,节能减排的楷模。

唯一不能确定的是,它走下去会不会产生误差。这得看CSS的功力,它的内部机制的运行效率直接决定了我们这个时钟未来的命运。

马黑黑 发表于 2022-3-20 12:39

可以沿用刻度盘时钟里的思路获的时间信息,要注意的是,这里我们要处理24、12小时制的问题:

var now = new Date();
var        hr = now.getHours() > 12 ? now.getHours() - 12 : now.getHours(),
        min = now.getMinutes(),
        sec = now.getSeconds(),
        msec = now.getMilliseconds(); //毫秒

注意我们用了偷懒的变量声明法,var 带三个变量,变量之间用逗号隔开,直至最后一个用分号标识声明结束。下面是关键,计算时分秒指针第一推动力的角度,也就是按当前时间时分秒毫秒数结合圆周进行计算,让三个指针各归其位:

var        hDeg = hr * 30 + (min * 6 / 12),
        mDeg = min * 6 + (sec * 6 / 60),
        sDeg = sec * 6 + (msec * 0.36 / 1000);


hDeg 是指针初始化角度,小时数乘以30指向当前钟点数的位置。为什么乘以30呢?圆盘有360度,布置12个钟点位置,每一个钟点位置从上一个点到它这里占据的弧度是 360/12=30,就是酱紫的。当前时间不一定是整点,所以要加上分钟应驱动时针去到的位置,加上 min*6/12,可是这个算式怎么来?一分钟占据的圆周弧度是6个单位(360/60),折算成小时占据的弧度要除以12(圆周上有12个钟点数)。搞定。

mDeg 是分针的初始化角度。当前的分钟数指向哪里? min*6 就是。为什么?上面说了,一分钟应占据6个弧度单位,我们获得的当前分钟数是 min 分,min分乘以6就是它应指向的分针刻度,然后要加上当前的秒数折算成零点几分钟,sec * 6 / 60,这个算式又是怎么弄的?在一分钟里面,每一秒钟应占据6个弧度单位,理由描述如下:秒针转一圈是一分钟,一圈是360度,一分钟是60秒,360度除以60秒就能得出一秒钟所占据的弧度单位,就是6了,最后要折算成分钟弧度,当然要除以60。

sDeg 是秒针初始化角度。同理,当前时间是 sec 秒,它指向 sec*6 的刻度方向,然后加上当前的毫秒数折算成零点几秒,(msec * 0.36 / 1000),这个算式又又又怎么来的?我们知道,1000毫秒等于一秒,所以每一毫秒在圆周上占据的弧度单位是 360度除以1000毫秒,360/1000=0.36,得出的结果再在除以1000才是 msec 毫秒所占据的零点几秒钟应占据的秒钟弧度单位。

以上这些算法看似复杂,但自有其原理,稍加思考便能理解。

各指针按当前时间的指向有了以上的角度依据,最后的工作就是去给指针依次“校时”,以秒针为例(假设秒针父元素的操作句柄是 miaozhen):

miaozhen.style.transform = “rotate(" + sDeg + "deg)"; //转动秒针 sDeg 个角度到当前时间秒针应当指向的位置

当然,我们要把这些实现机制封装在一个自定义函数里,以上的例句只是为了说明问题。

红影 发表于 2022-3-20 12:41

transform: rotate(1turn) 这个是什么单位?

红影 发表于 2022-3-20 12:43

漂亮,时针前面还有个小箭头,貌似分针前面也应该有个{:4_173:}

红影 发表于 2022-3-20 12:46

这个真漂亮,写成太不容易了,黑黑辛苦了{:4_187:}

马黑黑 发表于 2022-3-20 13:15

红影 发表于 2022-3-20 12:41
transform: rotate(1turn) 这个是什么单位?

等同于 rotate(360deg)

马黑黑 发表于 2022-3-20 13:16

红影 发表于 2022-3-20 12:43
漂亮,时针前面还有个小箭头,貌似分针前面也应该有个

我观察过很多时钟,分针的样式绝大多数都是一个矩形,老式的钟表分针才会用箭头或其他样式

马黑黑 发表于 2022-3-20 13:18

红影 发表于 2022-3-20 12:46
这个真漂亮,写成太不容易了,黑黑辛苦了

CSS代码会多一些,HTML代码也会多出几个节点

马黑黑 发表于 2022-3-20 13:19

红影 发表于 2022-3-20 12:46
这个真漂亮,写成太不容易了,黑黑辛苦了

turn 就是圈、转动一圈、轮到等意思,这里指圈,1turn 就是圆周的一圈,和360deg等价

红影 发表于 2022-3-21 10:48

马黑黑 发表于 2022-3-20 13:19
turn 就是圈、转动一圈、轮到等意思,这里指圈,1turn 就是圆周的一圈,和360deg等价

还可以这样用啊,习惯了360度,原来直接用这个单词也是一样的{:4_173:}

红影 发表于 2022-3-21 10:50

马黑黑 发表于 2022-3-20 13:16
我观察过很多时钟,分针的样式绝大多数都是一个矩形,老式的钟表分针才会用箭头或其他样式

力求真实显示现实,黑黑真细致{:4_199:}

红影 发表于 2022-3-21 10:54

马黑黑 发表于 2022-3-20 13:18
CSS代码会多一些,HTML代码也会多出几个节点

这个特别清晰,所以多几个节点也也能理解{:4_187:}

马黑黑 发表于 2022-3-21 12:50

红影 发表于 2022-3-21 10:50
力求真实显示现实,黑黑真细致

网络就是生活的一部分,所以网络呈现的元素应该与现实的保持大概的一致

马黑黑 发表于 2022-3-21 12:51

红影 发表于 2022-3-21 10:48
还可以这样用啊,习惯了360度,原来直接用这个单词也是一样的

如果涉及到运算,还是用 deg 做单位较好。

红影 发表于 2022-3-21 18:53

马黑黑 发表于 2022-3-21 12:50
网络就是生活的一部分,所以网络呈现的元素应该与现实的保持大概的一致

这也得会代码的人才行呢,否则实现不了啊{:4_173:}

红影 发表于 2022-3-21 18:53

马黑黑 发表于 2022-3-21 12:51
如果涉及到运算,还是用 deg 做单位较好。

哦哦,好的。

马黑黑 发表于 2022-3-21 19:48

红影 发表于 2022-3-21 18:53
哦哦,好的。

{:4_190:}

马黑黑 发表于 2022-3-21 19:48

红影 发表于 2022-3-21 18:53
这也得会代码的人才行呢,否则实现不了啊

那是前提
页: [1] 2
查看完整版本: 让CSS驱动我们的数字盘时钟