主页/jQuery教程/综合实战项目/jQuery项目二:响应式图片画廊与灯箱

jQuery项目二:响应式图片画廊与灯箱

6,729字
28–43 分钟

概览

目录

本项目旨在综合运用 jQuery 的强大功能,构建一个具备响应式布局和灯箱(Lightbox)预览效果的图片画廊。通过此项目,将串联起 jQuery 响应式图片 处理、DOM 操作、事件绑定、动画效果以及插件开发思想等多个核心知识点。最终实现的画廊不仅能在不同屏幕尺寸下优雅地展示缩略图,还能在用户点击图片时,以模态框的形式展示大图,并提供流畅的切换动画,完整呈现一个现代 Web 项目中常见的交互组件。

项目结构与 HTML 基础

一个良好的项目始于清晰的 HTML 结构。画廊的基础由一组包含缩略图的链接构成,这些链接指向对应的高清大图。这种结构本身即使在 JavaScript 加载失败或未启用时,也能保证用户可以通过点击链接直接查看原始图片,体现了渐进增强的理念。

示例:画廊的 HTML 骨架

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery 响应式图片画廊项目</title>
    <link rel="stylesheet" href="gallery.css">
</head>
<body>
    <h1>jQuery 响应式图片画廊</h1>
    <div class="gallery-container">
        <div class="gallery" id="gallery">
            <a href="images/large/photo1.jpg" class="gallery-item" data-caption="夕阳下的海岸">
                <img src="images/thumb/photo1-thumb.jpg" alt="海岸风景缩略图" loading="lazy">
            </a>
            <a href="images/large/photo2.jpg" class="gallery-item" data-caption="城市夜景">
                <img src="images/thumb/photo2-thumb.jpg" alt="城市夜景缩略图" loading="lazy">
            </a>
            <a href="images/large/photo3.jpg" class="gallery-item" data-caption="山间晨雾">
                <img src="images/thumb/photo3-thumb.jpg" alt="山间晨雾缩略图" loading="lazy">
            </a>
            <!-- 更多图片项 -->
        </div>
    </div>
    <!-- 灯箱结构将由 jQuery 动态生成并插入此处 -->
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="gallery.js"></script>
</body>
</html>

在此结构中,gallery-item 链接的 href 指向大图,内部的 img 标签展示缩略图,并使用了 loading="lazy" 属性实现原生的懒加载。data-caption 属性用于存储图片标题,供灯箱显示。这种语义化的标记为后续的 jQuery 增强提供了坚实的基础。

CSS 样式与响应式布局

响应式图片 的实现依赖于灵活的 CSS 规则。通过媒体查询和弹性盒布局,确保画廊在不同设备上都能呈现出良好的视觉效果。

示例:画廊的 CSS (gallery.css)

/* 基础重置与容器 */
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: sans-serif; background: #f4f4f4; padding: 20px; }
h1 { text-align: center; margin-bottom: 30px; color: #333; }

/* 画廊网格容器 */
.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 15px;
    max-width: 1200px;
    margin: 0 auto;
}

/* 画廊项样式 */
.gallery-item {
    display: block;
    overflow: hidden;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    background: #fff;
    text-decoration: none; /* 移除链接下划线 */
}

.gallery-item:hover {
    transform: scale(1.03);
    box-shadow: 0 8px 16px rgba(0,0,0,0.2);
}

/* 响应式图片:确保图片完全填充容器 */
.gallery-item img {
    width: 100%;
    height: 100%;
    object-fit: cover; /* 保持比例,裁剪多余部分 */
    display: block;
}

/* 灯箱样式 (初始隐藏) */
.lightbox {
    display: none;
    position: fixed;
    top: 0; left: 0; width: 100%; height: 100%;
    background-color: rgba(0, 0, 0, 0.9);
    z-index: 1000;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}

.lightbox.active {
    display: flex; /* 通过类来控制显示 */
}

.lightbox-content {
    max-width: 90%;
    max-height: 80%;
    object-fit: contain;
    border: 5px solid #fff;
    border-radius: 4px;
    box-shadow: 0 0 20px rgba(255,255,255,0.2);
}

.lightbox-caption {
    color: #fff;
    margin-top: 15px;
    font-size: 1.1em;
    text-align: center;
}

.lightbox-close,
.lightbox-prev,
.lightbox-next {
    position: absolute;
    background: rgba(255,255,255,0.1);
    color: white;
    border: none;
    font-size: 2em;
    cursor: pointer;
    padding: 10px 20px;
    border-radius: 5px;
    transition: background 0.2s;
}
.lightbox-close { top: 20px; right: 30px; }
.lightbox-prev { left: 30px; top: 50%; transform: translateY(-50%); }
.lightbox-next { right: 30px; top: 50%; transform: translateY(-50%); }
.lightbox-close:hover,
.lightbox-prev:hover,
.lightbox-next:hover { background: rgba(255,255,255,0.3); }

上述 CSS 定义了画廊网格和灯箱的样式。grid 布局自动适应容器宽度,实现响应式排列。灯箱默认隐藏,通过 active 类控制显示,其中的图片和按钮样式确保了在暗色背景下的清晰可见。

jQuery 核心交互:构建灯箱

jQuery 负责为静态的 HTML 注入生命力,实现灯箱的动态创建、图片切换和事件处理。整个灯箱结构将在页面加载完成后由 jQuery 动态创建并插入到 <body> 中。

示例:jQuery 灯箱逻辑 (gallery.js)

$(document).ready(function() {
    // --- 动态创建灯箱 DOM 结构 ---
    var $lightbox = $('<div class="lightbox">' +
        '<button class="lightbox-close">&times;</button>' +
        '<button class="lightbox-prev">&#10094;</button>' +
        '<img class="lightbox-content" src="" alt="大图预览">' +
        '<button class="lightbox-next">&#10095;</button>' +
        '<div class="lightbox-caption"></div>' +
    '</div>').appendTo('body');

    var $lightboxImg = $lightbox.find('.lightbox-content');
    var $lightboxCaption = $lightbox.find('.lightbox-caption');
    var $galleryItems = $('.gallery-item');
    var currentIndex = 0;

    // --- 辅助函数:更新灯片内容 ---
    function updateLightbox(index) {
        var $item = $galleryItems.eq(index);
        $lightboxImg.attr('src', $item.attr('href')); // 从链接的 href 获取大图地址
        $lightboxCaption.text($item.data('caption')); // 获取 data-caption 属性
        currentIndex = index;
    }

    // --- 事件:点击缩略图打开灯箱 ---
    $galleryItems.on('click', function(e) {
        e.preventDefault(); // 阻止默认的链接跳转
        var index = $galleryItems.index(this); // 获取当前点击项的索引
        updateLightbox(index);
        $lightbox.addClass('active'); // 显示灯箱
    });

    // --- 事件:关闭灯箱 ---
    $lightbox.on('click', '.lightbox-close', function() {
        $lightbox.removeClass('active');
    });

    // --- 事件:点击灯箱背景关闭(可选)---
    $lightbox.on('click', function(e) {
        if (e.target === this) { // 确保点击的是背景本身,而非内部图片或按钮
            $lightbox.removeClass('active');
        }
    });

    // --- 事件:上一张 / 下一张 ---
    $lightbox.on('click', '.lightbox-prev', function(e) {
        e.stopPropagation(); // 防止事件冒泡触发背景关闭
        var newIndex = (currentIndex - 1 + $galleryItems.length) % $galleryItems.length;
        updateLightbox(newIndex);
    });

    $lightbox.on('click', '.lightbox-next', function(e) {
        e.stopPropagation();
        var newIndex = (currentIndex + 1) % $galleryItems.length;
        updateLightbox(newIndex);
    });

    // --- 键盘导航增强 ---
    $(document).on('keydown', function(e) {
        if (!$lightbox.hasClass('active')) return; // 只有灯箱激活时才响应

        switch(e.key) {
            case 'Escape':
                $lightbox.removeClass('active');
                break;
            case 'ArrowLeft':
                $lightbox.find('.lightbox-prev').click(); // 模拟点击上一张
                break;
            case 'ArrowRight':
                $lightbox.find('.lightbox-next').click(); // 模拟点击下一张
                break;
        }
    });
});

这段 jQuery 代码完成了以下核心任务:

  1. 动态创建:在文档加载完毕后,创建灯箱的 DOM 元素并添加到页面。
  2. 事件绑定:为缩略图链接绑定点击事件,阻止其默认行为,并更新灯箱内容后显示。
  3. 内容更新updateLightbox 函数根据索引从被点击的链接中提取大图 URL 和标题,更新灯箱内的图片和文字。
  4. 交互控制:实现了关闭按钮、背景点击关闭、上一张/下一张导航以及键盘(ESC,左右箭头)支持,极大地提升了用户体验。

项目扩展与插件思想

此项目可以视为一个基础的自定义“灯箱插件”。遵循 jQuery 插件开发的最佳实践,可以将其进一步封装,提升代码的复用性。

示例:将功能封装为 jQuery 插件

// 定义一个名为 "lightbox" 的 jQuery 插件
$.fn.lightbox = function(options) {
    // 默认设置
    var settings = $.extend({
        // 可以添加配置项,如动画速度、是否显示导航等
        animationSpeed: 300,
        showCaption: true
    }, options);

    // 针对每个匹配的元素(即 .gallery)进行处理
    return this.each(function() {
        var $gallery = $(this);
        var $items = $gallery.find('.gallery-item'); // 假设结构如之前所示

        // ... (将上述灯箱逻辑移入此处,但操作 DOM 时需使用局部变量,避免 ID 冲突)
        // 例如,动态创建的灯箱可以赋予一个基于时间戳的唯一 ID
        var lightboxId = 'lightbox-' + Date.now();
        var $lightbox = $('<div id="' + lightboxId + '" class="lightbox">...</div>').appendTo('body');

        // ... 其余事件绑定代码,确保选择器限定在 $lightbox 和 $items 内
    });
};

// 使用插件
$(document).ready(function() {
    $('#gallery').lightbox({ animationSpeed: 500 });
});

将核心逻辑封装成插件后,可以轻松地在页面的多个画廊实例上复用,并通过 options 参数进行定制,体现了 jQuery 代码的模块化和可扩展性。

版本变更记录

版本变更内容
1.0提供基础的 DOM 操作和事件绑定,为构建此类交互组件奠定基础。
1.4引入 .fadeIn() / .fadeOut() 等动画方法,可为灯箱添加平滑过渡效果。
1.7引入 .on() 方法,统一了事件处理,使得动态添加的灯箱元素也能有效绑定事件。
3.0优化了 $.extend() 等工具函数,便于插件开发中的默认参数合并。
4.0源代码迁移至 ES 模块,使得将此类组件与现代前端工具链集成更为顺畅。slim 版本移除了动画模块,若项目需要动画,应使用完整版或引入 polyfill。

浏览器兼容性

本项目使用的 jQuery 方法和 CSS 特性在以下浏览器版本中得到良好支持。

浏览器最低支持版本 (jQuery 3.x/4.x)
Chrome30+
Edge12+
Firefox25+
Opera18+
Safari7+
Chrome Android30+
Firefox for Android25+
Opera Android18+
Safari on iOS7+
Samsung Internet4.0+
WebView Android4.4+
WebView on iOS7+

注:CSS Grid 布局在非常古老的浏览器(如 IE 11)中需要 -ms- 前缀或使用备用布局方案。对于需要支持这些旧版浏览器的项目,可以考虑使用 Flexbox 作为替代方案来实现 响应式图片 布局。

通过本项目,可以清晰地看到 jQuery 如何在实际开发中整合多项技术,从一个语义化的 HTML 基础出发,逐步构建出一个功能完备、交互流畅且具备 响应式图片 处理能力的现代画廊组件。这不仅巩固了对 jQuery 各核心模块的理解,也展示了其在实际项目中的强大生产力。