求助:实现自动滚动Slider视口居中图片放大效果(CSS/JS)
实现自动滚动Slider的中心元素放大效果
我有一个自动滚动的Slider,希望当img元素处于视口中心时放大,离开中心后恢复原尺寸;下一个元素到达视口中心时同样放大,离开后恢复,循环往复。以下是我的HTML和CSS代码:
原HTML代码:
</head> <body> <section class="slider"> <ul> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> <li> <img src="https://placehold.co/600x400" alt="" class="elementSlide"> <div class="center">Hi<br>Hello World</div> </li> </ul> </section> </body>
原CSS代码:
.slider { overflow: hidden; } .slider ul { display: flex; justify-content: center; align-items: center; width: max-content; animation: runSlider 20s linear infinite; } .slider img { width: 40vw; height: 25vw; border-radius: 5vw; } .slider li { display: flex; justify-content: start; align-items: center; margin-right: 5vw; color: white; position: relative; height: 40vw; } .center { position: absolute; top: 50%; right: 10%; transform: translate(0%, -50%); font-size: 4vw; text-align: end; text-shadow: 1px 1px black; } @keyframes runSlider { from { transform: translateX(0); } to { transform: translateX(calc(-45vw * 4)); } }
方案一:纯CSS实现(基于动画同步)
利用CSS动画同步特性,让缩放动画与滚动动画时长一致,精准控制每个图片在到达视口中心时放大。
修改后的CSS代码:
.slider { overflow: hidden; position: relative; /* 可选:添加中心参考线,方便调试 */ /* &::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 2px; height: 100%; background: red; } */ } .slider ul { display: flex; justify-content: center; align-items: center; width: max-content; animation: runSlider 20s linear infinite; } .slider img { width: 40vw; height: 25vw; border-radius: 5vw; transition: transform 0.3s ease; /* 平滑过渡缩放效果 */ animation: zoom 20s linear infinite; /* 同步滚动时长的缩放动画 */ } .slider li { display: flex; justify-content: start; align-items: center; margin-right: 5vw; color: white; position: relative; height: 40vw; } .center { position: absolute; top: 50%; right: 10%; transform: translate(0%, -50%); font-size: 4vw; text-align: end; text-shadow: 1px 1px black; } @keyframes runSlider { from { transform: translateX(0); } to { transform: translateX(calc(-45vw * 4)); } } /* 缩放动画:与滚动动画时长一致,关键帧对应元素到达中心的时间点 */ @keyframes zoom { /* 8个元素,20s滚动周期,每个元素间隔2.5s到达中心 */ 0%, 10.4%, 35.4%, 60.4%, 85.4%, 100% { transform: scale(1); /* 非中心状态 */ } 12.5%, 37.5%, 62.5%, 87.5% { transform: scale(1.2); /* 中心状态,放大1.2倍 */ } } /* 为每个图片设置延迟,匹配各自到达中心的时间 */ .slider li:nth-child(1) img { animation-delay: 0s; } .slider li:nth-child(2) img { animation-delay: -2.5s; } .slider li:nth-child(3) img { animation-delay: -5s; } .slider li:nth-child(4) img { animation-delay: -7.5s; } .slider li:nth-child(5) img { animation-delay: -10s; } .slider li:nth-child(6) img { animation-delay: -12.5s; } .slider li:nth-child(7) img { animation-delay: -15s; } .slider li:nth-child(8) img { animation-delay: -17.5s; }
注意事项:
- 关键帧百分比需要根据元素数量和滚动时长调整,确保缩放时机与元素到达中心的时间完全同步。
- 若修改滚动时长或元素数量,需重新计算间隔时间和关键帧百分比。
方案二:JavaScript实现(动态检测)
如果需要适配窗口大小变化、动态调整元素数量等场景,用JS实时检测元素位置更灵活。
修改后的CSS(新增放大类):
.slider { overflow: hidden; } .slider ul { display: flex; justify-content: center; align-items: center; width: max-content; animation: runSlider 20s linear infinite; } .slider img { width: 40vw; height: 25vw; border-radius: 5vw; transition: transform 0.3s ease; /* 平滑过渡 */ } /* 放大样式类 */ .slider img.zoom { transform: scale(1.2); } .slider li { display: flex; justify-content: start; align-items: center; margin-right: 5vw; color: white; position: relative; height: 40vw; } .center { position: absolute; top: 50%; right: 10%; transform: translate(0%, -50%); font-size: 4vw; text-align: end; text-shadow: 1px 1px black; } @keyframes runSlider { from { transform: translateX(0); } to { transform: translateX(calc(-45vw * 4)); } }
JavaScript代码:
const sliderImgs = document.querySelectorAll('.elementSlide'); let viewportCenterX = window.innerWidth / 2; // 检测元素是否处于视口中心范围 function checkCenterPosition() { sliderImgs.forEach(img => { const rect = img.getBoundingClientRect(); const imgCenterX = rect.left + rect.width / 2; // 设定50px的阈值,元素中心进入该范围时放大 const isInCenter = Math.abs(imgCenterX - viewportCenterX) < 50; img.classList.toggle('zoom', isInCenter); }); } // 初始检测 checkCenterPosition(); // 持续检测动画状态 function animateCheck() { checkCenterPosition(); requestAnimationFrame(animateCheck); } animateCheck(); // 窗口大小变化时更新视口中心 window.addEventListener('resize', () => { viewportCenterX = window.innerWidth / 2; });
优势:
- 无需手动计算关键帧,自动适配元素位置变化。
- 支持窗口大小动态调整,兼容性更强。
内容的提问来源于stack exchange,提问作者Haitham
相关产品推荐
相关产品推荐

