/**
* 图片轮播组件
*/
class Carousel {
constructor(container, images) {
this.container = container;
this.images = images || [];
this.currentIndex = 0;
this.init();
}
init() {
if (this.images.length === 0) {
this.container.innerHTML = '
暂无图片
';
return;
}
this.render();
this.bindEvents();
}
render() {
const html = `
${this.images.map((img, index) => `

`).join('')}
${this.images.length > 1 ? `
${this.images.map((_, index) => `
`).join('')}
` : ''}
`;
this.container.innerHTML = html;
}
bindEvents() {
if (this.images.length <= 1) return;
// 上一张
const prevBtn = this.container.querySelector('[data-carousel-prev]');
if (prevBtn) {
prevBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.prev();
});
}
// 下一张
const nextBtn = this.container.querySelector('[data-carousel-next]');
if (nextBtn) {
nextBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.next();
});
}
// 指示器点击
const indicators = this.container.querySelectorAll('[data-carousel-indicator]');
indicators.forEach(indicator => {
indicator.addEventListener('click', (e) => {
e.stopPropagation();
const index = parseInt(indicator.getAttribute('data-carousel-indicator'));
this.goTo(index);
});
});
// 图片点击打开模态框
const imgElements = this.container.querySelectorAll('.carousel-image');
imgElements.forEach(img => {
img.addEventListener('click', () => {
this.openModal(this.currentIndex);
});
});
// 键盘快捷键
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') this.prev();
if (e.key === 'ArrowRight') this.next();
});
}
prev() {
this.currentIndex = (this.currentIndex - 1 + this.images.length) % this.images.length;
this.update();
}
next() {
this.currentIndex = (this.currentIndex + 1) % this.images.length;
this.update();
}
goTo(index) {
this.currentIndex = index;
this.update();
}
update() {
const track = this.container.querySelector('[data-carousel-track]');
if (track) {
track.style.transform = `translateX(-${this.currentIndex * 100}%)`;
}
// 更新指示器
const indicators = this.container.querySelectorAll('[data-carousel-indicator]');
indicators.forEach((indicator, index) => {
indicator.classList.toggle('active', index === this.currentIndex);
});
}
openModal(startIndex) {
ImageModal.open(this.images, startIndex);
}
}
/**
* 图片查看器模态框
*/
class ImageModal {
static modal = null;
static images = [];
static currentIndex = 0;
static init() {
this.modal = document.getElementById('image-modal');
if (!this.modal) return;
const overlay = document.getElementById('modal-overlay');
const closeBtn = document.getElementById('modal-close');
const prevBtn = document.getElementById('modal-prev');
const nextBtn = document.getElementById('modal-next');
// 关闭
overlay?.addEventListener('click', () => this.close());
closeBtn?.addEventListener('click', () => this.close());
// 切换
prevBtn?.addEventListener('click', () => this.prev());
nextBtn?.addEventListener('click', () => this.next());
// 键盘
document.addEventListener('keydown', (e) => {
if (!this.modal?.classList.contains('active')) return;
if (e.key === 'Escape') this.close();
if (e.key === 'ArrowLeft') this.prev();
if (e.key === 'ArrowRight') this.next();
});
}
static open(images, startIndex = 0) {
this.images = images;
this.currentIndex = startIndex;
this.show();
}
static show() {
if (!this.modal) return;
this.modal.classList.add('active');
this.updateImage();
document.body.style.overflow = 'hidden';
}
static close() {
if (!this.modal) return;
this.modal.classList.remove('active');
document.body.style.overflow = '';
}
static prev() {
this.currentIndex = (this.currentIndex - 1 + this.images.length) % this.images.length;
this.updateImage();
}
static next() {
this.currentIndex = (this.currentIndex + 1) % this.images.length;
this.updateImage();
}
static updateImage() {
const img = document.getElementById('modal-image');
const caption = document.getElementById('modal-caption');
if (img) {
img.src = this.images[this.currentIndex];
}
if (caption) {
caption.textContent = `${this.currentIndex + 1} / ${this.images.length}`;
}
}
}
// 初始化模态框
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => ImageModal.init());
} else {
ImageModal.init();
}