以下是纯前端实现的方案,只需在页面底部添加以下 JavaScript 代码即可实现多图浏览功能:

<script>
// 全屏图库样式(动态注入)
const galleryStyle = document.createElement('style');
galleryStyle.textContent = `
.gallery-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0,0,0,0.95);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: zoom-out;
}

.gallery-image {
    max-width: 90vw;
    max-height: 90vh;
    object-fit: contain;
    transition: opacity 0.3s;
}

.gallery-nav {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    background: rgba(255,255,255,0.8);
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
}

.gallery-prev { left: 20px; }
.gallery-next { right: 20px; }

.gallery-counter {
    position: fixed;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    color: white;
    font-size: 14px;
}
`;
document.head.appendChild(galleryStyle);

class ImageViewer {
    constructor() {
        this.images = [];
        this.currentIndex = 0;
        this.initGallery();
    }

    initGallery() {
        // 获取文章内所有图片
        const article = document.querySelector('#article-container');
        this.images = Array.from(article.querySelectorAll('img[data-src]'));
        
        // 添加点击事件
        this.images.forEach((img, index) => {
            img.dataset.index = index;
            img.style.cursor = 'zoom-in';
            img.addEventListener('click', (e) => this.open(e.target));
        });
    }

    open(targetImg) {
        this.currentIndex = parseInt(targetImg.dataset.index);
        this.createOverlay();
        this.showImage();
        this.bindEvents();
    }

    createOverlay() {
        this.overlay = document.createElement('div');
        this.overlay.className = 'gallery-overlay';
        
        this.imageEl = document.createElement('img');
        this.imageEl.className = 'gallery-image';
        
        this.prevBtn = this.createButton('❮', 'gallery-prev');
        this.nextBtn = this.createButton('❯', 'gallery-next');
        this.counter = this.createCounter();
        
        this.overlay.append(this.prevBtn, this.imageEl, this.nextBtn, this.counter);
        document.body.appendChild(this.overlay);
        document.body.style.overflow = 'hidden';
    }

    createButton(text, className) {
        const btn = document.createElement('div');
        btn.className = `gallery-nav ${className}`;
        btn.textContent = text;
        return btn;
    }

    createCounter() {
        const counter = document.createElement('div');
        counter.className = 'gallery-counter';
        return counter;
    }

    showImage() {
        this.imageEl.src = this.images[this.currentIndex].dataset.src;
        this.counter.textContent = `${this.currentIndex + 1} / ${this.images.length}`;
        this.toggleNavButtons();
    }

    toggleNavButtons() {
        this.prevBtn.style.display = this.currentIndex > 0 ? 'flex' : 'none';
        this.nextBtn.style.display = this.currentIndex < this.images.length - 1 ? 'flex' : 'none';
    }

    bindEvents() {
        // 按钮点击
        this.prevBtn.addEventListener('click', () => this.navigate(-1));
        this.nextBtn.addEventListener('click', () => this.navigate(1));
        
        // 遮罩点击
        this.overlay.addEventListener('click', (e) => {
            if (e.target === this.overlay) this.close();
        });
        
        // 键盘事件
        this.keyHandler = (e) => {
            switch(e.key) {
                case 'ArrowLeft': this.navigate(-1); break;
                case 'ArrowRight': this.navigate(1); break;
                case 'Escape': this.close(); break;
            }
        };
        document.addEventListener('keydown', this.keyHandler);
        
        // 触摸事件
        this.touchStartX = 0;
        this.overlay.addEventListener('touchstart', (e) => {
            this.touchStartX = e.touches[0].clientX;
        });
        this.overlay.addEventListener('touchend', (e) => {
            const deltaX = e.changedTouches[0].clientX - this.touchStartX;
            if (Math.abs(deltaX) > 50) {
                this.navigate(deltaX > 0 ? -1 : 1);
            }
        });
    }

    navigate(offset) {
        this.currentIndex += offset;
        if (this.currentIndex < 0) this.currentIndex = this.images.length - 1;
        if (this.currentIndex >= this.images.length) this.currentIndex = 0;
        this.showImage();
    }

    close() {
        document.body.removeChild(this.overlay);
        document.body.style.overflow = '';
        document.removeEventListener('keydown', this.keyHandler);
    }
}

// 初始化图库
document.addEventListener('DOMContentLoaded', () => {
    new ImageViewer();
});
</script>

实现特点:

  1. 纯前端实现:无需修改后端代码,只需添加 JS 即可
  2. 自动绑定事件
    • 自动查找 #article-container 内的所有懒加载图片
    • 自动添加点击事件和光标样式
  3. 交互功能
    • 左右箭头按钮导航
    • 键盘方向键控制(← → ESC)
    • 移动端触摸滑动切换
    • 图片计数器显示
  4. 性能优化
    • 使用原生懒加载图片地址(data-src)
    • 自动处理边界循环
    • 动态创建/销毁 DOM 元素
  5. 样式隔离
    • 动态注入 CSS 样式
    • 使用高 z-index 确保覆盖层级
    • 响应式图片显示

使用说明:

  1. 点击任意图片进入全屏模式
  2. 支持以下操作:
    • 点击左右箭头切换
    • 使用键盘方向键切换
    • 移动端左右滑动切换
    • 点击背景/按 ESC 键退出
  3. 左上角显示当前图片位置 (X/Y)

注意事项:

  1. 确保图片父容器 ID 为 #article-container
  2. 依赖图片的 data-src 属性获取原图地址
  3. 自动忽略已加载的 src 占位图
  4. 与现有懒加载库兼容(只需保持 data-src 属性)

如果需要添加加载动画,可以在 showImage() 方法中添加以下代码:

// 在 showImage() 开头添加
this.imageEl.style.opacity = 0;
const loader = document.createElement('div');
loader.style.cssText = `
    position: absolute;
    top: 50%;
    left: 50%;
    width: 30px;
    height: 30px;
    border: 3px solid rgba(255,255,255,0.3);
    border-radius: 50%;
    border-top-color: white;
    animation: spin 1s linear infinite;
`;
this.overlay.appendChild(loader);

// 在图片加载完成后
this.imageEl.onload = () => {
    this.imageEl.style.opacity = 1;
    loader.remove();
};

// 在样式表中添加
@keyframes spin {
    to { transform: rotate(360deg); }
}

以下是纯前端实现的方案,只需在页面底部添加以下 JavaScript 代码即可实现多图浏览功能: