You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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();
  };
};

关键优化点

  1. 避免重复绑定事件:原来的代码在每个画廊元素的点击事件中重复绑定prev/next按钮的事件,现在把这些事件绑定移到全局,只绑定一次。
  2. 统一的媒体控制:用active类切换显示状态,逻辑更清晰。
  3. 视频处理:添加controls属性让用户能控制播放,关闭lightbox时暂停视频。
  4. 扩展名大小写兼容:转成小写判断,避免因为文件名是.MP4导致识别错误。

内容的提问来源于stack exchange,提问作者theBlob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:20:52