如何用Vanilla JS实现同时展示图片与视频的幻灯片
解决Vanilla JS幻灯片同时展示图片和视频的问题
问题根源
你尝试直接修改img元素的tagName来切换成video,但DOM元素的标签名是只读属性,无法直接修改,所以这个方法无效。
解决方案:同时保留img和video元素,切换显示状态
最直观的方法是在lightbox容器中预先放置img和video元素,根据当前媒体的类型(图片/视频)切换它们的显示状态。
步骤1:修改HTML结构
在lightbox_container中添加video标签,并给两者都加上统一的类名,方便控制样式:
<div class="lightbox"> <button class="lightbox_close">X</button> <button class="lightbox_next">Next</button> <button class="lightbox_previous">Prev</button> <div class="lightbox_container"> <img src="" class="lightbox_picture" alt=""> <video class="lightbox_picture" controls></video> <!-- 添加controls属性支持播放控制 --> <h2 class="lightbox_picture_title"></h2> </div> </div>
步骤2:添加基础CSS控制显示
初始状态下隐藏所有媒体元素,只有添加active类的元素才显示:
.lightbox_picture { display: none; max-width: 100%; max-height: 80vh; } .lightbox_picture.active { display: block; }
步骤3:重构JS代码
重新组织逻辑,用全局的currentIndex跟踪当前媒体位置,根据扩展名切换显示的元素:
window.onload = () => { // 选择所有DOM元素 const gallery = document.querySelectorAll('.profil_image'); const totalGallery = gallery.length; const lightbox = document.querySelector('.lightbox'); const lightboxImg = document.querySelector('.lightbox_container img'); const lightboxVideo = document.querySelector('.lightbox_container video'); const lightboxTitle = document.querySelector('.lightbox_picture_title'); const closeButton = document.querySelector('.lightbox_close'); const prevBtn = document.querySelector('.lightbox_previous'); const nextBtn = document.querySelector('.lightbox_next'); let currentIndex = 0; // 预览媒体的核心函数 function preview(index) { const mediaUrl = gallery[index].src; const mediaTitle = gallery[index].alt; lightboxTitle.textContent = mediaTitle; // 获取文件扩展名并转小写,避免大小写问题 const extension = mediaUrl.split('.').pop().toLowerCase(); // 先隐藏所有媒体元素 lightboxImg.classList.remove('active'); lightboxVideo.classList.remove('active'); // 根据扩展名切换显示对应的元素 if (extension === 'jpg') { lightboxImg.src = mediaUrl; lightboxImg.classList.add('active'); } else if (extension === 'mp4') { lightboxVideo.src = mediaUrl; lightboxVideo.classList.add('active'); } // 控制前后按钮的显示状态 prevBtn.style.display = index === 0 ? 'none' : 'block'; nextBtn.style.display = index >= totalGallery - 1 ? 'none' : 'block'; } // 绑定画廊元素的点击事件 gallery.forEach((item, index) => { item.onclick = () => { currentIndex = index; preview(currentIndex); lightbox.classList.add("show"); }; }); // 上一张按钮逻辑 prevBtn.onclick = () => { if (currentIndex > 0) { currentIndex--; preview(currentIndex); } }; // 下一张按钮逻辑 nextBtn.onclick = () => { if (currentIndex < totalGallery - 1) { currentIndex++; preview(currentIndex); } }; // 关闭lightbox逻辑 closeButton.onclick = () => { lightbox.classList.remove("show"); // 关闭时暂停视频,避免后台继续播放 lightboxVideo.pause(); }; };
关键优化点
- 避免重复绑定事件:原来的代码在每个画廊元素的点击事件中重复绑定prev/next按钮的事件,现在把这些事件绑定移到全局,只绑定一次。
- 统一的媒体控制:用
active类切换显示状态,逻辑更清晰。 - 视频处理:添加
controls属性让用户能控制播放,关闭lightbox时暂停视频。 - 扩展名大小写兼容:转成小写判断,避免因为文件名是
.MP4导致识别错误。
内容的提问来源于stack exchange,提问作者theBlob
相关产品推荐
相关产品推荐

