实现响应式图片查看器:轻量级lightbox解决方案

  Java   20分钟   457浏览   0评论

你好呀,我是小邹。

在现代Web开发中,lightbox组件是一种常见的增强用户体验的方法,它允许用户在不离开当前页面的情况下查看和操作图片。本文将引导你构建一个轻量级的lightbox,具备基本的图片放大、缩小以及关闭功能,并且兼容桌面和移动设备。

引言

Lightbox不仅增强了网站的视觉吸引力,还提供了更流畅的用户交互体验。在本文中,我们将探讨如何创建一个简易但功能齐全的lightbox,包括:

  • 响应式设计,确保在不同设备上良好显示。
  • 图片的放大与缩小功能。
  • 使用CSS和JavaScript实现的平滑动画和交互。

效果图

image-20240708172614544

image-20240708172624899

准备工作

在开始之前,请确保你熟悉HTML、CSS和JavaScript的基本知识。我们的目标是创建一个可以嵌入任何网页的lightbox,无需引入额外的库或框架。

设计lightbox

首先,我们定义lightbox的HTML结构。它将包含一个用于显示图片的<img>元素,以及两个用于控制图片缩放的按钮。

<div id="lightbox" style="display:none;">
    <img id="lightboxImg">
    <button id="zoomIn" class="zoomButton">+</button>
    <button id="zoomOut" class="zoomButton">-</button>
</div>

接下来,我们编写CSS样式来美化lightbox并使其具有响应性。

#lightbox {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.8);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 9999;
}

#lightbox img {
    max-width: 90%;
    max-height: 90%;
}

#lightbox .zoomButton {
    position: absolute;
    bottom: 10px;
    width: 40px;
    height: 40px;
    border-radius: 50%; /* 圆形按钮 */
    font-size: 24px;
    line-height: 40px; /* 文字垂直居中 */
    text-align: center; /* 文字水平居中 */
    cursor: pointer;
    color: white;
    background-color: rgba(255, 255, 255, 0.5); /* 半透明白色背景 */
    border: none;
    transition: background-color 0.3s ease; /* 平滑过渡效果 */
}

#lightbox .zoomButton:hover {
    background-color: rgba(255, 255, 255, 0.8); /* 鼠标悬停时加深背景色 */
}

#zoomIn {
    right: 10px;
}

#zoomOut {
    right: 60px;
}

实现交互逻辑

现在,我们通过JavaScript来实现lightbox的功能。我们将监听图片点击事件以显示lightbox,同时监听滚轮事件和按钮点击事件以调整图片的大小。

document.addEventListener('DOMContentLoaded', function () {
    // ...JavaScript代码...
});

显示lightbox

当用户点击任何图片时,lightbox应显示该图片。

var images = document.querySelectorAll('img');
images.forEach(function (image) {
    image.addEventListener('click', function (event) {
        lightboxImg.src = this.src;
        lightbox.style.display = 'flex';
    });
});

缩放功能

利用滚轮事件和按钮点击事件,我们可以轻松地增加或减少图片的缩放比例。

var scale = 1;

lightboxImg.addEventListener('wheel', function (event) {
    event.preventDefault();
    scale -= event.deltaY > 0 ? 0.1 : -0.1;
    scale = Math.min(Math.max(0.1, scale), 3);
    updateTransform();
}, { passive: false });

zoomInButton.addEventListener('click', function () {
    scale += 0.1;
    scale = Math.min(3, scale);
    updateTransform();
});

zoomOutButton.addEventListener('click', function () {
    scale -= 0.1;
    scale = Math.max(0.1, scale);
    updateTransform();
});

更新图片变换

我们需要一个辅助函数来更新图片的transform样式。

function updateTransform() {
    lightboxImg.style.transform = `scale(${scale})`;
}

关闭lightbox

最后,我们需要一个方法来关闭lightbox,当用户点击lightbox的背景时。

lightbox.addEventListener('click', function (event) {
    if (event.target === this) {
        lightbox.style.display = 'none';
    }
});

完整JavaScript代码

<script type="application/javascript">
    document.addEventListener('DOMContentLoaded', function () {
        var images = document.querySelectorAll('img');
        var lightbox = document.getElementById('lightbox');
        var lightboxImg = document.getElementById('lightboxImg');
        var zoomInButton = document.getElementById('zoomIn');
        var zoomOutButton = document.getElementById('zoomOut');
        var scale = 1; // 图片缩放比例
        var offsetX = 0; // 图片水平偏移量
        var offsetY = 0; // 图片垂直偏移量

        // 初始化图片位置和缩放
        updateTransform();

        // 为每个图片添加点击事件处理器
        images.forEach(function (image) {
            image.addEventListener('click', function (event) {
                event.stopPropagation();
                lightboxImg.src = this.src;
                scale = 1; // 重置缩放比例
                offsetX = 0; // 重置偏移量
                offsetY = 0;
                updateTransform();
                lightbox.style.display = 'flex';
            });
        });

        // 为lightbox添加点击事件处理器,用于关闭lightbox
        lightbox.addEventListener('click', function (event) {
            if (event.target === this) {
                lightbox.style.display = 'none';
            }
        });

        // 更新图片的transform样式
        function updateTransform() {
            lightboxImg.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`;
        }

        // 监听滚轮事件,实现图片缩放
        lightboxImg.addEventListener('wheel', function (event) {
            event.preventDefault(); // 阻止默认行为(滚动页面)
            scale -= event.deltaY > 0 ? 0.1 : -0.1; // 上滑放大,下滑缩小
            scale = Math.min(Math.max(0.1, scale), 3); // 确保缩放比例在合理范围内
            updateTransform();
        }, { passive: false }); // 使用{passive: false}以阻止默认行为

        // 为放大按钮添加事件处理器
        zoomInButton.addEventListener('click', function () {
            scale += 0.1; // 放大
            scale = Math.min(3, scale); // 确保不超过最大值
            updateTransform();
        });

        // 为缩小按钮添加事件处理器
        zoomOutButton.addEventListener('click', function () {
            scale -= 0.1; // 缩小
            scale = Math.max(0.1, scale); // 确保不低于最小值
            updateTransform();
        });

        // 手机端触摸缩放和拖动逻辑
        var touchStartX, touchStartY, touchStartScale;
        var isDragging = false;
        var lastTouchMoveX, lastTouchMoveY;

        // 处理触摸开始事件
        lightboxImg.addEventListener('touchstart', function (event) {
            if (event.touches.length === 2) {
                touchStartX = (event.touches[0].pageX + event.touches[1].pageX) / 2;
                touchStartY = (event.touches[0].pageY + event.touches[1].pageY) / 2;
                touchStartScale = scale;
            } else if (event.touches.length === 1) {
                lastTouchMoveX = event.touches[0].pageX;
                lastTouchMoveY = event.touches[0].pageY;
            }
        }, { passive: false });

        // 处理触摸移动事件
        lightboxImg.addEventListener('touchmove', function (event) {
            if (event.touches.length === 2) {
                const x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
                const y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
                const distance = Math.sqrt(Math.pow(event.touches[0].pageX - event.touches[1].pageX, 2) + Math.pow(event.touches[0].pageY - event.touches[1].pageY, 2));
                const initialDistance = Math.sqrt(Math.pow(touchStartX - event.touches[0].pageX, 2) + Math.pow(touchStartY - event.touches[0].pageY, 2));
                scale = touchStartScale * (distance / initialDistance);
                scale = Math.min(Math.max(0.1, scale), 3);

                // 移动图片中心点到触摸点
                const dx = x - touchStartX;
                const dy = y - touchStartY;
                offsetX += dx;
                offsetY += dy;
                updateTransform();
            } else if (event.touches.length === 1 && !isDragging) {
                const dx = event.touches[0].pageX - lastTouchMoveX;
                const dy = event.touches[0].pageY - lastTouchMoveY;
                offsetX += dx;
                offsetY += dy;
                lastTouchMoveX = event.touches[0].pageX;
                lastTouchMoveY = event.touches[0].pageY;
                updateTransform();
                isDragging = true;
            }
        }, { passive: false });

        // 处理触摸结束事件
        lightboxImg.addEventListener('touchend', function () {
            isDragging = false;
        });
    });
</script>

结论

通过上述步骤,我们成功创建了一个简单的lightbox,具备基本的图片预览、放大、缩小功能,同时具有优雅的外观和良好的用户体验。这个lightbox可以轻松地集成到任何网页项目中,无需依赖外部库,是一个完美的自定义解决方案。

如果你觉得文章对你有帮助,那就请作者喝杯咖啡吧☕
微信
支付宝
  0 条评论