LoadinG

动态进度时钟时间与日期的视觉化展示Html代码

本文阅读 1 分钟
首页 程序代码 正文

这个项目是一个动态的进度时钟,通过视觉化的方式展示当前的时间和日期。时钟不仅显示小时、分钟和秒,还通过环形进度条展示当前月份的天数、小时、分钟和秒的进度。用户可以通过点击不同的时间单位(如小时、分钟等)来查看对应的进度条变化。时钟的设计采用了现代简约风格,支持深色模式,并且会根据用户的系统设置自动切换主题。通过JavaScript动态更新时间和进度条,确保时钟的实时性和准确性。

Html代码:

<html>
<head>
    <style>
        * {
            border: 0;
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        :root {
            --hue: 223;
            --bg: hsl(var(--hue), 10%, 90%);
            --fg: hsl(var(--hue), 10%, 10%);
            font-size: calc(16px + (24 - 16) * (100vw - 320px) / (1280 - 320));
        }

        body,
        button {
            color: #fff;
            font: 1em/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
        }

        body {
            background-color: #d9e1ff;
            height: 100vh;
            display: grid;
            place-items: center;
        }

        .progress-clock {
            display: grid;
            justify-content: center;
            align-content: center;
            position: relative;
            text-align: center;
            width: 16em;
            height: 16em;
        }

        .progress-clock__time-date,
        .progress-clock__time-digit,
        .progress-clock__time-colon,
        .progress-clock__time-ampm {
            transition: color 0.2s linear;
            -webkit-user-select: none;
            -moz-user-select: none;
            user-select: none;
        }

        .progress-clock__time-date,
        .progress-clock__time-digit {
            background: transparent;
        }

        .progress-clock__time-date,
        .progress-clock__time-ampm {
            grid-column: 1 / 6;
        }

        .progress-clock__time-date {
            font-size: 0.75em;
            line-height: 1.33;
        }

        .progress-clock__time-digit,
        .progress-clock__time-colon {
            font-size: 2em;
            font-weight: 400;
            grid-row: 2;
        }

        .progress-clock__time-colon {
            line-height: 1.275;
        }

        .progress-clock__time-ampm {
            cursor: default;
            grid-row: 3;
        }

        .progress-clock__rings {
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -1;
        }

        .progress-clock__ring {
            opacity: 0.1;
        }

        .progress-clock__ring-fill {
            transition:
                opacity 0s 0.3s linear,
                stroke-dashoffset 0.3s ease-in-out;
        }

        .progress-clock__ring-fill--360 {
            opacity: 0;
            stroke-dashoffset: 0;
            transition-duration: 0.3s;
        }

        [data-group]:focus {
            outline: transparent;
        }

        [data-units] {
            transition: opacity 0.2s linear;
        }

        [data-group="d"]:focus,
        [data-group="d"]:hover {
            color: hsl(333, 90%, 55%);
        }

        [data-group="h"]:focus,
        [data-group="h"]:hover {
            color: hsl(33, 90%, 55%);
        }

        [data-group="m"]:focus,
        [data-group="m"]:hover {
            color: hsl(213, 90%, 55%);
        }

        [data-group="s"]:focus,
        [data-group="s"]:hover {
            color: hsl(273, 90%, 55%);
        }

        [data-group]:focus~.progress-clock__rings [data-units],
        [data-group]:hover~.progress-clock__rings [data-units] {
            opacity: 0.2;
        }

        [data-group="d"]:focus~.progress-clock__rings [data-units="d"],
        [data-group="d"]:hover~.progress-clock__rings [data-units="d"],
        [data-group="h"]:focus~.progress-clock__rings [data-units="h"],
        [data-group="h"]:hover~.progress-clock__rings [data-units="h"],
        [data-group="m"]:focus~.progress-clock__rings [data-units="m"],
        [data-group="m"]:hover~.progress-clock__rings [data-units="m"],
        [data-group="s"]:focus~.progress-clock__rings [data-units="s"],
        [data-group="s"]:hover~.progress-clock__rings [data-units="s"] {
            opacity: 1;
        }

        @media (prefers-color-scheme: dark) {
            :root {
                --bg: hsl(var(--hue), 10%, 10%);
                --fg: hsl(var(--hue), 10%, 90%);
            }

            .progress-clock__ring {
                opacity: 0.2;
            }
        }
    </style>
</head>

<body>
    <div id="clock" class="progress-clock">
        <button class="progress-clock__time-date" data-group="d" type="button">
            <small data-unit="w">Sunday</small><br>
            <span data-unit="mo">January</span>
            <span data-unit="d">1</span>
        </button>
        <button class="progress-clock__time-digit" data-unit="h" data-group="h" type="button">12</button><span
            class="progress-clock__time-colon">:</span><button class="progress-clock__time-digit" data-unit="m"
            data-group="m" type="button">00</button><span class="progress-clock__time-colon">:</span><button
            class="progress-clock__time-digit" data-unit="s" data-group="s" type="button">00</button>
        <span class="progress-clock__time-ampm" data-unit="ap">AM</span>
        <svg class="progress-clock__rings" width="256" height="256" viewBox="0 0 256 256">
            <defs>
                <linearGradient id="pc-red" x1="1" y1="0.5" x2="0" y2="0.5">
                    <stop offset="0%" stop-color="hsl(343,90%,55%)" />
                    <stop offset="100%" stop-color="hsl(323,90%,55%)" />
                </linearGradient>
                <linearGradient id="pc-yellow" x1="1" y1="0.5" x2="0" y2="0.5">
                    <stop offset="0%" stop-color="hsl(43,90%,55%)" />
                    <stop offset="100%" stop-color="hsl(23,90%,55%)" />
                </linearGradient>
                <linearGradient id="pc-blue" x1="1" y1="0.5" x2="0" y2="0.5">
                    <stop offset="0%" stop-color="hsl(223,90%,55%)" />
                    <stop offset="100%" stop-color="hsl(203,90%,55%)" />
                </linearGradient>
                <linearGradient id="pc-purple" x1="1" y1="0.5" x2="0" y2="0.5">
                    <stop offset="0%" stop-color="hsl(283,90%,55%)" />
                    <stop offset="100%" stop-color="hsl(263,90%,55%)" />
                </linearGradient>
            </defs>
            <g data-units="d">
                <circle class="progress-clock__ring" cx="128" cy="128" r="74" fill="none" opacity="0.1"
                    stroke="url(#pc-red)" stroke-width="12" />
                <circle class="progress-clock__ring-fill" data-ring="mo" cx="128" cy="128" r="74" fill="none"
                    stroke="url(#pc-red)" stroke-width="12" stroke-dasharray="465 465" stroke-dashoffset="465"
                    stroke-linecap="round" transform="rotate(-90,128,128)" />
            </g>
            <g data-units="h">
                <circle class="progress-clock__ring" cx="128" cy="128" r="90" fill="none" opacity="0.1"
                    stroke="url(#pc-yellow)" stroke-width="12" />
                <circle class="progress-clock__ring-fill" data-ring="d" cx="128" cy="128" r="90" fill="none"
                    stroke="url(#pc-yellow)" stroke-width="12" stroke-dasharray="565.5 565.5" stroke-dashoffset="565.5"
                    stroke-linecap="round" transform="rotate(-90,128,128)" />
            </g>
            <g data-units="m">
                <circle class="progress-clock__ring" cx="128" cy="128" r="106" fill="none" opacity="0.1"
                    stroke="url(#pc-blue)" stroke-width="12" />
                <circle class="progress-clock__ring-fill" data-ring="h" cx="128" cy="128" r="106" fill="none"
                    stroke="url(#pc-blue)" stroke-width="12" stroke-dasharray="666 666" stroke-dashoffset="666"
                    stroke-linecap="round" transform="rotate(-90,128,128)" />
            </g>
            <g data-units="s">
                <circle class="progress-clock__ring" cx="128" cy="128" r="122" fill="none" opacity="0.1"
                    stroke="url(#pc-purple)" stroke-width="12" />
                <circle class="progress-clock__ring-fill" data-ring="m" cx="128" cy="128" r="122" fill="none"
                    stroke="url(#pc-purple)" stroke-width="12" stroke-dasharray="766.5 766.5" stroke-dashoffset="766.5"
                    stroke-linecap="round" transform="rotate(-90,128,128)" />
            </g>
        </svg>
    </div>
</body>
<script>
    window.addEventListener("DOMContentLoaded", () => {
        const clock = new ProgressClock("#clock");
    });

    class ProgressClock {
        constructor(qs) {
            this.el = document.querySelector(qs);
            this.time = 0;
            this.updateTimeout = null;
            this.ringTimeouts = [];
            this.update();
        }
        getDayOfWeek(day) {
            switch (day) {
                case 1:
                    return "Monday";
                case 2:
                    return "Tuesday";
                case 3:
                    return "Wednesday";
                case 4:
                    return "Thursday";
                case 5:
                    return "Friday";
                case 6:
                    return "Saturday";
                default:
                    return "Sunday";
            }
        }
        getMonthInfo(mo, yr) {
            switch (mo) {
                case 1:
                    return {
                        name: "February", days: yr % 4 === 0 ? 29 : 28
                    };
                case 2:
                    return {
                        name: "March", days: 31
                    };
                case 3:
                    return {
                        name: "April", days: 30
                    };
                case 4:
                    return {
                        name: "May", days: 31
                    };
                case 5:
                    return {
                        name: "June", days: 30
                    };
                case 6:
                    return {
                        name: "July", days: 31
                    };
                case 7:
                    return {
                        name: "August", days: 31
                    };
                case 8:
                    return {
                        name: "September", days: 30
                    };
                case 9:
                    return {
                        name: "October", days: 31
                    };
                case 10:
                    return {
                        name: "November", days: 30
                    };
                case 11:
                    return {
                        name: "December", days: 31
                    };
                default:
                    return {
                        name: "January", days: 31
                    };
            }
        }
        update() {
            this.time = new Date();

            if (this.el) {
                const dayOfWeek = this.time.getDay();
                const year = this.time.getFullYear();
                const month = this.time.getMonth();
                const day = this.time.getDate();
                const hr = this.time.getHours();
                const min = this.time.getMinutes();
                const sec = this.time.getSeconds();
                const dayOfWeekName = this.getDayOfWeek(dayOfWeek);
                const monthInfo = this.getMonthInfo(month, year);
                const m_progress = sec / 60;
                const h_progress = (min + m_progress) / 60;
                const d_progress = (hr + h_progress) / 24;
                const mo_progress = ((day - 1) + d_progress) / monthInfo.days;
                const units = [{
                    label: "w",
                    value: dayOfWeekName
                },
                {
                    label: "mo",
                    value: monthInfo.name,
                    progress: mo_progress
                },
                {
                    label: "d",
                    value: day,
                    progress: d_progress
                },
                {
                    label: "h",
                    value: hr > 12 ? hr - 12 : hr,
                    progress: h_progress
                },
                {
                    label: "m",
                    value: min < 10 ? "0" + min : min,
                    progress: m_progress
                },
                {
                    label: "s",
                    value: sec < 10 ? "0" + sec : sec
                },
                {
                    label: "ap",
                    value: hr > 12 ? "PM" : "AM"
                }
                ];
                this.ringTimeouts.forEach(t => {
                    clearTimeout(t);
                });
                this.ringTimeouts = [];
                units.forEach(u => {
                    const ring = this.el.querySelector(`[data-ring="${u.label}"]`);

                    if (ring) {
                        const strokeDashArray = ring.getAttribute("stroke-dasharray");
                        const fill360 = "progress-clock__ring-fill--360";

                        if (strokeDashArray) {
                            const circumference = +strokeDashArray.split(" ")[0];
                            const strokeDashOffsetPct = 1 - u.progress;

                            ring.setAttribute(
                                "stroke-dashoffset",
                                strokeDashOffsetPct * circumference
                            );
                            if (strokeDashOffsetPct === 1) {
                                ring.classList.add(fill360);

                                this.ringTimeouts.push(
                                    setTimeout(() => {
                                        ring.classList.remove(fill360);
                                    }, 600)
                                );
                            }
                        }
                    }
                    const unit = this.el.querySelector(`[data-unit="${u.label}"]`);

                    if (unit)
                        unit.innerText = u.value;
                });
            }

            clearTimeout(this.updateTimeout);
            this.updateTimeout = setTimeout(this.update.bind(this), 1e3);
        }
    }
</script>
</html>
文章采用:署名-非商业性使用-相同方式知识共享 署名 4.0 协议国际版 (CC BY-NC-SA 4.0) 许可协议授权。
免责声明:本页面资源来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系客服并出示版权证明以便删除。
分享
苹果新款妙控鼠标或将集成AI语音控制,提升用户体验
« 上一篇 12-31
优化 Google AdSense 广告代码以提升网站加载速度的实用指南
下一篇 » 12-31

发表评论 Comment

您必须 后才能发表评论哦~
昵称
请输入您的昵称
邮箱
输入QQ邮箱可获取头像
网址
可通过昵称访问您网站
快捷回复: 验证码:
让大家也知道你的独特见解
已有 0 条评论

动态快讯

热门文章

QQ客服:3236485 QQ群号:530123520

在线时间:09:00-18:00

扫描二维码

联系官方客服微信号

扫描二维码

关注官方微信公众号

{"error":400,"message":"over quota"}