You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
8.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 户用轮播图交互功能
*/
class HouseholdCarousel {
constructor(container) {
this.container = container;
this.track = container.querySelector('.household-carousel-track');
this.slides = container.querySelectorAll('.household-slide');
this.prevBtn = container.querySelector('.household-carousel-prev');
this.nextBtn = container.querySelector('.household-carousel-next');
// 移除指示器相关代码
this.currentSlide = 0;
this.totalSlides = this.slides.length;
this.isAnimating = false;
this.autoPlayInterval = null;
this.autoPlayDelay = 5000; // 5秒自动切换
// 触摸相关属性
this.touchStartX = 0;
this.touchEndX = 0;
this.touchThreshold = 50;
this.init();
}
init() {
if (this.totalSlides <= 1) {
this.hideControls();
return;
}
this.bindEvents();
this.startAutoPlay();
this.preloadImages();
// 设置初始状态
this.updateSlide(0, false);
}
bindEvents() {
// 控制按钮事件
if (this.prevBtn) {
this.prevBtn.addEventListener('click', () => this.prevSlide());
}
if (this.nextBtn) {
this.nextBtn.addEventListener('click', () => this.nextSlide());
}
// 移除指示器事件绑定
// 触摸事件
this.container.addEventListener('touchstart', (e) => this.handleTouchStart(e), { passive: true });
this.container.addEventListener('touchend', (e) => this.handleTouchEnd(e), { passive: true });
// 鼠标悬停暂停自动播放
this.container.addEventListener('mouseenter', () => this.stopAutoPlay());
this.container.addEventListener('mouseleave', () => this.startAutoPlay());
// 键盘导航
this.container.addEventListener('keydown', (e) => this.handleKeydown(e));
// 窗口失焦暂停自动播放
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
this.stopAutoPlay();
} else {
this.startAutoPlay();
}
});
// 窗口大小改变时重新计算
window.addEventListener('resize', () => this.handleResize());
}
prevSlide() {
if (this.isAnimating) return;
const prevIndex = this.currentSlide === 0 ? this.totalSlides - 1 : this.currentSlide - 1;
this.updateSlide(prevIndex);
}
nextSlide() {
if (this.isAnimating) return;
const nextIndex = this.currentSlide === this.totalSlides - 1 ? 0 : this.currentSlide + 1;
this.updateSlide(nextIndex);
}
goToSlide(index) {
if (this.isAnimating || index === this.currentSlide) return;
this.updateSlide(index);
}
updateSlide(index, animate = true) {
if (this.isAnimating) return;
this.isAnimating = animate;
// 更新当前幻灯片
this.slides[this.currentSlide].classList.remove('active');
this.slides[index].classList.add('active');
// 移除指示器更新代码
// 更新轨道数据属性
this.track.setAttribute('data-current-slide', index);
this.currentSlide = index;
// 动画完成后重置状态
if (animate) {
setTimeout(() => {
this.isAnimating = false;
}, 500);
} else {
this.isAnimating = false;
}
// 触发自定义事件
this.container.dispatchEvent(new CustomEvent('slideChange', {
detail: { currentSlide: this.currentSlide, totalSlides: this.totalSlides }
}));
}
startAutoPlay() {
if (this.totalSlides <= 1) return;
this.stopAutoPlay();
this.autoPlayInterval = setInterval(() => {
this.nextSlide();
}, this.autoPlayDelay);
}
stopAutoPlay() {
if (this.autoPlayInterval) {
clearInterval(this.autoPlayInterval);
this.autoPlayInterval = null;
}
}
preloadImages() {
this.slides.forEach((slide, index) => {
const img = slide.querySelector('img');
if (img && index > 0) {
// 预加载非首张图片
const preloadImg = new Image();
preloadImg.src = img.src;
}
});
}
handleTouchStart(e) {
this.touchStartX = e.touches[0].clientX;
}
handleTouchEnd(e) {
this.touchEndX = e.changedTouches[0].clientX;
this.handleSwipe();
}
handleSwipe() {
const swipeDistance = this.touchStartX - this.touchEndX;
if (Math.abs(swipeDistance) > this.touchThreshold) {
if (swipeDistance > 0) {
// 向左滑动,显示下一张
this.nextSlide();
} else {
// 向右滑动,显示上一张
this.prevSlide();
}
}
}
handleKeydown(e) {
switch (e.key) {
case 'ArrowLeft':
e.preventDefault();
this.prevSlide();
break;
case 'ArrowRight':
e.preventDefault();
this.nextSlide();
break;
case 'Home':
e.preventDefault();
this.goToSlide(0);
break;
case 'End':
e.preventDefault();
this.goToSlide(this.totalSlides - 1);
break;
}
}
handleResize() {
// 防抖处理
clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(() => {
// 重新计算布局
this.updateSlide(this.currentSlide, false);
}, 250);
}
hideControls() {
if (this.prevBtn) this.prevBtn.style.display = 'none';
if (this.nextBtn) this.nextBtn.style.display = 'none';
// 移除指示器隐藏代码
}
// 公共API方法
getCurrentSlide() {
return this.currentSlide;
}
getTotalSlides() {
return this.totalSlides;
}
setAutoPlayDelay(delay) {
this.autoPlayDelay = delay;
if (this.autoPlayInterval) {
this.startAutoPlay();
}
}
destroy() {
this.stopAutoPlay();
// 移除事件监听器
if (this.prevBtn) {
this.prevBtn.removeEventListener('click', () => this.prevSlide());
}
if (this.nextBtn) {
this.nextBtn.removeEventListener('click', () => this.nextSlide());
}
// 移除指示器事件清理代码
this.container.removeEventListener('touchstart', (e) => this.handleTouchStart(e));
this.container.removeEventListener('touchend', (e) => this.handleTouchEnd(e));
this.container.removeEventListener('mouseenter', () => this.stopAutoPlay());
this.container.removeEventListener('mouseleave', () => this.startAutoPlay());
this.container.removeEventListener('keydown', (e) => this.handleKeydown(e));
}
}
// 初始化所有轮播图
function initHouseholdCarousels() {
const carousels = document.querySelectorAll('.household-carousel-block');
const instances = [];
carousels.forEach(carousel => {
const instance = new HouseholdCarousel(carousel);
instances.push(instance);
// 将实例存储到DOM元素上方便外部访问
carousel.householdCarousel = instance;
});
return instances;
}
// DOM加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initHouseholdCarousels);
} else {
initHouseholdCarousels();
}
// 导出类和初始化函数
window.HouseholdCarousel = HouseholdCarousel;
window.initHouseholdCarousels = initHouseholdCarousels;