滚动图片悬停效果优化:固定鼠标触发/中心显示名称需求
无限横向滚动图片的交互优化方案
基于Stack Overflow的《Making horizontal scroll with images infinite with no break CSS》实现了无限横向图片滚动效果,同时添加了hover悬停显示名称的功能,目前运行正常。现需优化以下交互:
- 鼠标固定在指定div上时,滚动经过该区域的图片自动触发悬停效果,无需移动鼠标即可依次查看图片名称
- 若上述需求无法实现,则改为当图片滚动至屏幕中心位置时,触发显示图片名称的效果
方案一:鼠标固定区域自动触发悬停
实现思路
- 监听滚动容器的
mouseenter和mouseleave事件,标记是否处于"观察状态" - 使用
requestAnimationFrame实时检测每个图片容器是否进入鼠标停留的目标区域(滚动容器的可视范围) - 为进入区域的图片容器添加激活类,强制显示名称overlay;离开区域时移除类
修改后的代码
CSS 新增样式
.container-img-strip.active .overlay-img-accueil { opacity: 1; }
JavaScript 逻辑
在原HTML的script标签末尾添加以下代码:
const scrollContainer = document.querySelector('.scroll'); const imgContainers = document.querySelectorAll('.container-img-strip'); let isObserving = false; // 监听鼠标进入/离开滚动容器 scrollContainer.addEventListener('mouseenter', () => { isObserving = true; checkActiveImages(); }); scrollContainer.addEventListener('mouseleave', () => { isObserving = false; // 清除所有激活状态 imgContainers.forEach(container => container.classList.remove('active')); }); // 实时检测图片是否进入可视区域 function checkActiveImages() { if (!isObserving) return; const scrollRect = scrollContainer.getBoundingClientRect(); imgContainers.forEach(container => { const rect = container.getBoundingClientRect(); // 判断图片容器是否在滚动容器的可视范围内 const isInView = rect.right > scrollRect.left && rect.left < scrollRect.right; if (isInView) { container.classList.add('active'); } else { container.classList.remove('active'); } }); requestAnimationFrame(checkActiveImages); }
方案二:图片滚动至屏幕中心触发显示
实现思路
- 计算屏幕中心的坐标
- 使用
requestAnimationFrame实时检测每个图片容器的中心是否与屏幕中心重合(或进入指定范围) - 符合条件的图片容器添加激活类,显示名称overlay
修改后的代码
CSS 新增样式
.container-img-strip.active .overlay-img-accueil { opacity: 1; }
JavaScript 逻辑
在原HTML的script标签末尾添加以下代码:
const imgContainers = document.querySelectorAll('.container-img-strip'); let centerX = window.innerWidth / 2; const triggerRange = 100; // 触发范围,可根据需求调整 function checkCenterImages() { imgContainers.forEach(container => { const rect = container.getBoundingClientRect(); const imgCenterX = rect.left + rect.width / 2; // 判断图片中心是否在屏幕中心的触发范围内 const isInCenter = Math.abs(imgCenterX - centerX) < triggerRange; if (isInCenter) { container.classList.add('active'); } else { container.classList.remove('active'); } }); requestAnimationFrame(checkCenterImages); } // 页面加载后启动检测 window.addEventListener('load', checkCenterImages); // 窗口大小改变时重新计算中心坐标 window.addEventListener('resize', () => { centerX = window.innerWidth / 2; });
原基础代码回顾
CSS
.m-scroll { overflow: hidden; white-space: nowrap; animation: scrollText 300s infinite linear; margin: 0; font-size: 0; display: flex; justify-content: space-between; align-items: center; width: fit-content; } .header { background-color: #223654; color: #223654; padding: 0px; box-sizing: border-box; text-align: center; background-size: cover; position: fixed; width: 100%; top: 34px; height: auto; z-index: 21; display: block; } .scroll { position: relative; width: 100%; background-color: transparent; overflow: hidden; z-index: 1; margin: 0 0px; padding: 0; border: 2px solid #223654; } span.insidescroller { display: inline-block; width: fit-content; margin: 0 0px; padding: 0; color: white; } @keyframes scrollText { from { transform: translateX(0%); } to { transform: translateX(-90%); } } .containeur-flex-row-accueil { display: grid; gap: 0px; grid-auto-flow: column; grid-template-rows: 1fr; overflow-x: auto; overflow-y: visible; } .img-index-photo { width: 100%; height: 100%; margin: 0; border: 2px solid #223654; object-fit: cover; box-sizing: border-box; aspect-ratio: 1/1; } .container-img-strip { width: 100px; height: 100px; position: relative; } .container-img-strip:hover .overlay-img-accueil { opacity: 1; } .img-scroll-accueil { width: 100px; height: 100px; margin: 0; border: 2px solid #223654; object-fit: cover; box-sizing: border-box; aspect-ratio: 1/1; } .overlay-img-accueil { position: absolute; top: 0; bottom: 0; left: 0; right: 0; height: 100%; width: 100%; opacity: 0; transition: 0.5s ease; background-color: rgba(34, 54, 84, 0.7); } .text-overlay-accueil { color: white; font-size: 12px; position: absolute; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%); text-align: center; user-select: none; }
HTML
<div id="header-logo" class="header"> <div class="scroll"> <div class="m-scroll"> <span class="insidescroller"> <div class="containeur-flex-row-accueil"> <script> /* 实际站点中为PHP生成 */ j = 1; for (let i = 1; i <= 20; i++) { for (let i = 1; i <= 10; i++) { j++; document.write(` <a href="#"> <div class="container-img-strip"> <img class="img-scroll-accueil" src="https://viogene.net/fixed-images/mush-${i}.jpg"> <div class="overlay-img-accueil"> <div class="text-overlay-accueil">Mushroom #${j}<br>name </div> </div> </div> </a> `); } } /* PHP生成代码结束 */ </script> </div> </span> </div> </div> </div>
内容的提问来源于stack exchange,提问作者Alex Vio
相关产品推荐
相关产品推荐

