如何在鼠标悬停轮播中为上一幻灯片设置指定z-index?
问题描述
想要制作一个基于鼠标悬停切换的轮播组件,通过z-index控制幻灯片的显示层级,具体需求如下:
- 所有幻灯片默认z-index: 1
- 当前显示的幻灯片设置z-index: 3
- 切换至新幻灯片时,将上一个幻灯片设为z-index: 2,新幻灯片设为3
当前代码实现如下:
HTML代码
<ul class='slider-navigation'> <li data-slide='1'>Slide 1</li> <li data-slide='2'>Slide 2</li> <li data-slide='3'>Slide 3</li> </ul> <div> <img class='slide' data-slide='1' src='https://images.unsplash.com/photo-1669818319938-bb7029dc3fa3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwzfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&q=60'> <img class='slide' data-slide='2' src='https://images.unsplash.com/photo-1669623313981-6af02eedb15c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw1fHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&q=60'> <img class='slide' data-slide='3' src='https://images.unsplash.com/photo-1446776811953-b23d57bd21aa?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTF8fHNwYWNlfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60' /> </div>
CSS代码
img { z-index: var(--z-index); position: absolute; top: 0; left: 0; width: 200px; height: 150px; object-fit: cover; } div { height: 200px; width: 200px; position: relative; } img.slideIn { animation: slideIn 2s ease forwards; } @keyframes slideIn { from { translate: 200px; } to { translate: 0px; } }
JavaScript代码
slides = document.querySelectorAll('.slide'); navItems = document.querySelectorAll('.slider-navigation li'); navItems.forEach(navItem => { navItem.addEventListener('mouseover', () => onNavigationHover(navItem)); }); function onNavigationHover(navItem) { let slideKey = navItem.dataset.slide; slides.forEach((slide, index) => { if (slide.dataset.slide === slideKey) { slide.style.setProperty('--z-index', 3) // can i set the previous slide zIndex here to 2? slide.classList.add('slideIn') } else { slide.style.setProperty('--z-index', 1) slide.classList.remove('slideIn') } }); }
当前代码能实现基本切换,但始终有一张图片固定在下层,询问是否可以保存上一个幻灯片的索引并设置不同z-index,或者有其他合适的实现思路。
解决方案
可以通过保存上一个幻灯片的引用来实现需求,以下是两种可行的实现方式:
方式一:通过全局变量记录当前激活幻灯片
核心是维护一个全局变量保存当前显示的幻灯片,每次切换时依次调整层级:
let slides = document.querySelectorAll('.slide'); let navItems = document.querySelectorAll('.slider-navigation li'); let currentActiveSlide = null; // 初始化:所有幻灯片设为z-index:1,默认激活第一张 slides.forEach(slide => { slide.style.setProperty('--z-index', 1); }); if (slides.length > 0) { currentActiveSlide = slides[0]; currentActiveSlide.style.setProperty('--z-index', 3); } navItems.forEach(navItem => { navItem.addEventListener('mouseover', () => onNavigationHover(navItem)); }); function onNavigationHover(navItem) { let slideKey = navItem.dataset.slide; const newActiveSlide = Array.from(slides).find(slide => slide.dataset.slide === slideKey); // 避免重复触发同一幻灯片 if (newActiveSlide === currentActiveSlide) return; // 调整上一个激活幻灯片的层级 if (currentActiveSlide) { currentActiveSlide.style.setProperty('--z-index', 2); currentActiveSlide.classList.remove('slideIn'); } // 设置新幻灯片的层级与动画 newActiveSlide.style.setProperty('--z-index', 3); newActiveSlide.classList.add('slideIn'); // 将其余幻灯片重置为z-index:1 slides.forEach(slide => { if (slide !== currentActiveSlide && slide !== newActiveSlide) { slide.style.setProperty('--z-index', 1); slide.classList.remove('slideIn'); } }); // 更新当前激活幻灯片的引用 currentActiveSlide = newActiveSlide; }
方式二:通过CSS类控制层级(更易维护)
将层级控制逻辑交给CSS,JS只负责切换类名,符合关注点分离原则:
修改后的CSS
img { z-index: 1; position: absolute; top: 0; left: 0; width: 200px; height: 150px; object-fit: cover; } img.active { z-index: 3; } img.previous { z-index: 2; } div { height: 200px; width: 200px; position: relative; } img.slideIn { animation: slideIn 2s ease forwards; } @keyframes slideIn { from { translate: 200px; } to { translate: 0px; } }
对应的JavaScript
let slides = document.querySelectorAll('.slide'); let navItems = document.querySelectorAll('.slider-navigation li'); // 初始化激活第一张幻灯片 if (slides.length > 0) { slides[0].classList.add('active'); } navItems.forEach(navItem => { navItem.addEventListener('mouseover', () => { const slideKey = navItem.dataset.slide; const newActiveSlide = Array.from(slides).find(s => s.dataset.slide === slideKey); if (newActiveSlide.classList.contains('active')) return; // 将当前激活幻灯片标记为上一张 const currentActive = document.querySelector('.slide.active'); if (currentActive) { currentActive.classList.remove('active'); currentActive.classList.add('previous'); currentActive.classList.remove('slideIn'); } // 清除其他幻灯片的上一张标记 slides.forEach(slide => { if (slide !== currentActive) { slide.classList.remove('previous'); } }); // 设置新幻灯片为当前激活状态 newActiveSlide.classList.add('active'); newActiveSlide.classList.add('slideIn'); }); });
内容的提问来源于stack exchange,提问作者SaroGFX
相关产品推荐
相关产品推荐

