倒计时组件

CutestUI 倒计时组件是一款优雅、功能丰富的时间倒计时工具,支持多种主题、大小和动画效果,适用于各种场景的倒计时展示需求。

组件概览

倒计时组件可以显示天、时、分、秒的剩余时间,并提供丰富的自定义选项。无论是活动倒计时、产品发布、限时优惠还是其他需要展示倒计时的场景,都可以使用这款组件来增强用户体验。

特性

  • 多种主题样式:支持主色调、成功、警告、信息、危险等5种内置主题
  • 灵活的大小控制:提供小型、大型和默认三种尺寸变体
  • 丰富的视觉效果:支持圆角、方块和玻璃拟态等多种视觉风格
  • 动态动画支持:包括脉冲、翻转和闪烁三种动画效果
  • 完整的响应式设计:适配各种屏幕尺寸
  • 无障碍支持:符合Web可访问性标准
  • 易于集成:提供简洁的API和使用指南
  • 高度可定制:支持自定义颜色、字体和动画效果

使用示例

基础示例

05
:
12
:
34
:
56

基础倒计时组件,显示天、时、分、秒,使用默认样式。

主题变体

05
:
12
:
34
05
:
12
:
34
05
:
12
:
34
05
:
12
:
34

不同主题变体的倒计时组件,从左到右:主色调、成功、警告、危险。

大小变体

05
:
12
05
:
12
05
:
12

不同大小的倒计时组件,从左到右:小型、中型(默认)、大型。

视觉效果

05
:
12
05
:
12
05
:
12

不同视觉效果的倒计时组件,从左到右:圆角、方块、玻璃拟态。

动画效果

05
:
12
00
:
00

不同动画效果的倒计时组件,从左到右:脉冲动画、闪烁动画、完成状态。

代码示例

HTML 结构

<!-- 基础倒计时组件 -->
<div id="my-countdown" class="cutest-countdown">
    <div class="cutest-countdown-block">
        <div class="cutest-countdown-number">05</div>
        <div class="cutest-countdown-label">天</div>
    </div>
    <div class="cutest-countdown-separator">:</div>
    <div class="cutest-countdown-block">
        <div class="cutest-countdown-number">12</div>
        <div class="cutest-countdown-label">时</div>
    </div>
    <div class="cutest-countdown-separator">:</div>
    <div class="cutest-countdown-block">
        <div class="cutest-countdown-number">34</div>
        <div class="cutest-countdown-label">分</div>
    </div>
    <div class="cutest-countdown-separator">:</div>
    <div class="cutest-countdown-block">
        <div class="cutest-countdown-number">56</div>
        <div class="cutest-countdown-label">秒</div>
    </div>
</div>

<!-- 主题变体示例 -->
<div class="cutest-countdown theme-primary">...</div>
<div class="cutest-countdown theme-success">...</div>
<div class="cutest-countdown theme-warning">...</div>
<div class="cutest-countdown theme-info">...</div>
<div class="cutest-countdown theme-danger">...</div>

<!-- 大小变体示例 -->
<div class="cutest-countdown size-small">...</div>
<div class="cutest-countdown size-large">...</div>

<!-- 视觉效果示例 -->
<div class="cutest-countdown rounded">...</div>
<div class="cutest-countdown square">...</div>
<div class="cutest-countdown glass">...</div>

<!-- 动画效果示例 -->
<div class="cutest-countdown animate-pulse">...</div>
<div class="cutest-countdown animate-blink">...</div>

JavaScript 实现

/**
 * CutestUI 倒计时组件
 */
class CutestCountdown {
    /**
     * 构造函数
     * @param {string} elementId - 倒计时元素ID
     * @param {Object} options - 配置选项
     */
    constructor(elementId, options = {}) {
        this.element = document.getElementById(elementId);
        if (!this.element) {
            console.error(`Element with id '${elementId}' not found`);
            return;
        }
        
        // 默认配置
        this.defaults = {
            targetDate: null, // 目标日期
            onTick: null,     // 每秒更新回调
            onComplete: null, // 倒计时完成回调
            format: 'dhms',   // 显示格式: d(天)h(时)m(分)s(秒)
            leadingZero: true // 是否显示前导零
        };
        
        // 合并配置
        this.options = { ...this.defaults, ...options };
        
        // 验证目标日期
        if (!this.options.targetDate) {
            console.error('targetDate is required');
            return;
        }
        
        this.targetDate = new Date(this.options.targetDate);
        this.interval = null;
        this.isCompleted = false;
        
        // 开始倒计时
        this.start();
    }
    
    /**
     * 开始倒计时
     */
    start() {
        // 立即更新一次
        this.update();
        
        // 设置定时器,每秒更新
        this.interval = setInterval(() => {
            this.update();
        }, 1000);
    }
    
    /**
     * 停止倒计时
     */
    stop() {
        if (this.interval) {
            clearInterval(this.interval);
            this.interval = null;
        }
    }
    
    /**
     * 更新倒计时显示
     */
    update() {
        if (this.isCompleted) return;
        
        const now = new Date();
        const diff = this.targetDate - now;
        
        // 检查是否已完成
        if (diff <= 0) {
            this.complete();
            return;
        }
        
        // 计算剩余时间
        const days = Math.floor(diff / (1000 * 60 * 60 * 24));
        const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
        const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
        const seconds = Math.floor((diff % (1000 * 60)) / 1000);
        
        // 格式化数字
        const formatNumber = (num) => {
            return this.options.leadingZero && num < 10 ? `0${num}` : `${num}`;
        };
        
        // 更新DOM
        const numbers = this.element.querySelectorAll('.cutest-countdown-number');
        const format = this.options.format;
        
        let index = 0;
        if (format.includes('d') && numbers[index]) {
            numbers[index++].textContent = formatNumber(days);
        }
        if (format.includes('h') && numbers[index]) {
            numbers[index++].textContent = formatNumber(hours);
        }
        if (format.includes('m') && numbers[index]) {
            numbers[index++].textContent = formatNumber(minutes);
        }
        if (format.includes('s') && numbers[index]) {
            numbers[index++].textContent = formatNumber(seconds);
        }
        
        // 触发tick回调
        if (typeof this.options.onTick === 'function') {
            this.options.onTick({
                days,
                hours,
                minutes,
                seconds,
                totalSeconds: Math.floor(diff / 1000)
            });
        }
    }
    
    /**
     * 倒计时完成处理
     */
    complete() {
        this.isCompleted = true;
        this.stop();
        
        // 更新显示为零
        const numbers = this.element.querySelectorAll('.cutest-countdown-number');
        numbers.forEach(number => {
            number.textContent = this.options.leadingZero ? '00' : '0';
        });
        
        // 添加完成状态类
        this.element.classList.add('completed');
        
        // 触发完成回调
        if (typeof this.options.onComplete === 'function') {
            this.options.onComplete();
        }
    }
    
    /**
     * 重置倒计时
     * @param {Date|string} newTargetDate - 新的目标日期
     */
    reset(newTargetDate = null) {
        this.stop();
        this.isCompleted = false;
        this.element.classList.remove('completed');
        
        if (newTargetDate) {
            this.options.targetDate = newTargetDate;
            this.targetDate = new Date(newTargetDate);
        }
        
        this.start();
    }
}

// 使用示例
// 初始化倒计时组件
// 注意:请在页面加载完成后初始化
// document.addEventListener('DOMContentLoaded', function() {
//     // 基础示例:设置7天后的日期作为目标日期
//     const targetDate = new Date();
//     targetDate.setDate(targetDate.getDate() + 7);
//     
//     const countdown = new CutestCountdown('my-countdown', {
//         targetDate: targetDate,
//         onTick: function(time) {
//             console.log('Remaining time:', time);
//         },
//         onComplete: function() {
//             console.log('Countdown completed!');
//             alert('倒计时结束!');
//         }
//     });
// });

使用指南

基本使用

  1. 引入 CSS 文件:<link rel="stylesheet" href="/public/static/css/countdowns.css">
  2. 创建 HTML 结构,按照上面的 HTML 代码示例
  3. 引入 JavaScript 代码(CutestCountdown 类)
  4. 在页面加载完成后初始化组件

配置选项

  • targetDate:目标日期,支持 Date 对象或日期字符串(必填)
  • onTick:每秒更新时的回调函数,接收一个包含 days, hours, minutes, seconds 的对象
  • onComplete:倒计时完成时的回调函数
  • format:显示格式,默认为 'dhms',可以自定义显示的时间单位
  • leadingZero:是否显示前导零,默认为 true

方法

  • start():开始倒计时
  • stop():停止倒计时
  • reset(newTargetDate):重置倒计时,可以选择设置新的目标日期

主题定制

倒计时组件支持多种主题变体,可以通过添加相应的类名来应用不同的主题:

  • 默认主题cutest-countdown
  • 主色调主题cutest-countdown theme-primary
  • 成功主题cutest-countdown theme-success
  • 警告主题cutest-countdown theme-warning
  • 信息主题cutest-countdown theme-info
  • 危险主题cutest-countdown theme-danger

您还可以通过自定义 CSS 来创建自己的主题:

/* 自定义主题示例 */
.cutest-countdown.theme-custom .cutest-countdown-number {
    background-color: #9c27b0; /* 自定义背景色 */
}

.cutest-countdown.theme-custom .cutest-countdown-label {
    color: #9c27b0; /* 自定义标签颜色 */
}

.cutest-countdown.theme-custom .cutest-countdown-separator {
    color: #9c27b0; /* 自定义分隔符颜色 */
}

常见问题

  • 问题:倒计时不更新
    解决方法:确保正确初始化了 CutestCountdown 类,并提供了有效的 targetDate
  • 问题:主题样式未生效
    解决方法:检查是否正确添加了主题类名,例如 theme-primary
  • 问题:在移动设备上显示异常
    解决方法:组件已内置响应式设计,请确保没有覆盖默认的响应式样式