|
|
/**
|
|
|
* 户用轮播图交互功能
|
|
|
*/
|
|
|
|
|
|
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; |