import { HomeVideo } from './HomeVideo.ts';
/**
* 首页模块
*/
export class Home {
private static runTimeInterval: number | null = null;
constructor() {
this.init();
}
private init(): void {
// 初始化首页视频模块
new HomeVideo();
// 运行时间计数器
this.initRunTimeCounter();
// 首页幻灯片
this.initHeroSlider();
}
/**
* 初始化运行时间计数器
*/
private initRunTimeCounter(): void {
const runTimeElement = document.getElementById('runTime');
const timeStr = runTimeElement?.dataset.startTime;
if (!timeStr) {
return;
}
const startTime: Date = new Date(timeStr);
if (Home.runTimeInterval) {
clearInterval(Home.runTimeInterval);
}
Home.runTimeInterval = window.setInterval(() => {
if (!runTimeElement) {
return;
}
const now: Date = new Date();
const diff = now.getTime() - startTime.getTime();
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);
runTimeElement.textContent = `已运行 ${days}天 ${hours}小时 ${minutes}分 ${seconds}秒`;
}, 1000);
}
/**
* 初始化首页幻灯片轮播
*/
private initHeroSlider(): void {
const heroBgsElements = document.querySelectorAll<HTMLElement>('.hero__bg');
if (heroBgsElements.length === 0) {
return;
}
let currentIndex = 0;
const heroTitle = document.getElementById('hero-title');
const heroCaption = document.getElementById('hero-caption');
const indicators = document.getElementById('hero-indicators');
if (!heroTitle || !heroCaption || !indicators) {
return;
}
const slideDuration = 5000;
let autoplayTimer: number | null = null;
let isPaused = false;
// 创建胶囊指示器
const createIndicators = (): void => {
indicators.innerHTML = '';
heroBgsElements.forEach((_, i) => {
const span = document.createElement('span');
span.className = 'hero__indicator';
span.dataset.index = i.toString();
indicators.appendChild(span);
});
};
// 更新指示器激活状态
const updateIndicator = (index: number): void => {
const dots = indicators.querySelectorAll<HTMLElement>('.hero__indicator');
dots.forEach((dot) => {
dot.classList.remove('is-active', 'is-animating');
});
const activeDot = dots[index];
if (activeDot) {
activeDot.classList.add('is-active');
// 强制 reflow 确保 animation 重新触发
void activeDot.offsetWidth;
activeDot.style.setProperty('--hero-progress-duration', `${slideDuration}ms`);
activeDot.classList.add('is-animating');
}
};
// 更新图片说明文字
const updateCaption = (desc: string | null): void => {
if (desc && desc !== '') {
heroCaption.textContent = desc;
heroCaption.classList.add('has-text');
} else {
heroCaption.classList.remove('has-text');
}
};
// 更新标题动画
const updateTitle = (desc: string | null): void => {
heroTitle.classList.remove('is-entering');
heroTitle.textContent = desc || '';
// 强制 reflow 后触发入场动画
void heroTitle.offsetWidth;
if (desc) {
heroTitle.classList.add('is-entering');
}
};
// 切换到指定幻灯片
const goToSlide = (nextIndex: number): void => {
const current = heroBgsElements[currentIndex];
const next = heroBgsElements[nextIndex];
if (!current || !next) {
return;
}
// 预加载背景图
const bgUrl = next.dataset.bg;
const currentBgImage = window.getComputedStyle(next).backgroundImage;
if (bgUrl && (!currentBgImage || currentBgImage === 'none')) {
next.style.backgroundImage = `url('${bgUrl}')`;
}
current.classList.remove('active');
next.classList.add('active');
const nextDesc = next.dataset.desc || null;
updateTitle(nextDesc);
updateCaption(nextDesc);
updateIndicator(nextIndex);
currentIndex = nextIndex;
};
// 初始化幻灯片
const initSlide = (): void => {
const first = heroBgsElements[0];
if (!first) {
return;
}
const bgUrl = first.dataset.bg;
if (bgUrl) {
first.style.backgroundImage = `url('${bgUrl}')`;
}
first.classList.add('active');
createIndicators();
updateIndicator(0);
const firstDesc = first.dataset.desc || null;
updateTitle(firstDesc);
updateCaption(firstDesc);
};
// 开始自动轮播
const startAutoplay = (): void => {
stopAutoplay();
if (heroBgsElements.length <= 1) {
return;
}
autoplayTimer = window.setInterval(() => {
goToSlide((currentIndex + 1) % heroBgsElements.length);
}, slideDuration);
};
// 停止自动轮播
const stopAutoplay = (): void => {
if (autoplayTimer !== null) {
clearInterval(autoplayTimer);
autoplayTimer = null;
}
};
// 初始化
initSlide();
// 指示器点击切换
indicators.addEventListener('click', (e: MouseEvent) => {
const target = e.target as HTMLElement;
if (!target.classList.contains('hero__indicator')) {
return;
}
const idx = parseInt(target.dataset.index || '0', 10);
if (idx === currentIndex) {
return;
}
goToSlide(idx);
// 点击后重置自动播放计时器(从头开始计时)
if (!isPaused) {
startAutoplay();
}
});
// 指示器悬停暂停
indicators.addEventListener('mouseenter', () => {
isPaused = true;
stopAutoplay();
});
indicators.addEventListener('mouseleave', () => {
isPaused = false;
startAutoplay();
});
// 启动自动轮播
startAutoplay();
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
这是一个 TypeScript 编写的首页模块代码,主要负责首页的交互功能实现。让我详细解释一下这个代码的结构和功能:
类概述
Home 类是首页的主控制器,负责初始化和管理首页的各个功能模块。
主要功能模块
1. 初始化方法 (init)
在构造函数中调用,负责启动三个主要功能:
- 初始化首页视频模块(通过
HomeVideo类) - 启动运行时间计数器
- 启动首页轮播图功能
2. 运行时间计数器 (initRunTimeCounter)
功能:显示网站运行时长的实时计数器
实现细节:
- 从 DOM 元素的
data-start-time属性获取起始时间 - 使用
setInterval每秒更新一次显示 - 计算并显示天、时、分、秒的差值
- 使用静态属性管理定时器,防止重复创建
3. 首页轮播图 (initHeroSlider)
功能:实现一个功能完整的图片轮播组件
核心特性:
- 自动轮播:每5秒自动切换到下一张
- 指示器导航:底部圆点指示器,可点击跳转
- 悬停暂停:鼠标悬停时暂停自动轮播
- 动画效果:标题入场动画和指示器进度动画
- 预加载优化:动态加载背景图片
详细实现:
指示器系统
const createIndicators = (): void => {
// 动态创建指示器圆点
// 每个圆点对应一张幻灯片
}
const updateIndicator = (index: number): void => {
// 更新指示器的激活状态
// 添加进度动画效果
}
内容更新
const updateTitle = (desc: string | null): void => {
// 更新标题并触发入场动画
}
const updateCaption = (desc: string | null): void => {
// 更新图片描述文字
}
核心切换逻辑
const goToSlide = (nextIndex: number): void => {
// 1. 预加载背景图片
// 2. 切换激活状态的CSS类
// 3. 更新标题、描述和指示器
}
自动播放控制
const startAutoplay = (): void => {
// 启动自动轮播定时器
}
const stopAutoplay = (): void => {
// 停止自动轮播
}
设计特点
1. 性能优化
- 图片懒加载:只在需要时加载背景图
- 定时器管理:防止内存泄漏
- 强制 reflow:确保动画正确触发
2. 用户体验
- 交互式控制:点击指示器直接跳转
- 智能暂停:悬停时暂停自动播放
- 平滑动画:CSS动画配合 JavaScript 控制
3. 代码健壮性
- 空值检查:防止 DOM 元素不存在导致的错误
- 边界处理:处理只有一张图片的情况
- 类型安全:完整的 TypeScript 类型注解
4. 模块化设计
- 单一职责:每个方法只负责一个具体功能
- 依赖注入:通过导入
HomeVideo模块 - 静态资源管理:使用静态属性管理全局状态
这个代码实现了一个现代化的首页交互系统,具备良好的用户体验和代码质量。
AI 正在分析代码…
评论加载中...