实现鼠标悬浮时溢出文本滚动至末尾,离开时平滑复位动画
实现文本容器悬浮滚动与平滑复位效果
要解决鼠标离开时文本直接跳回的问题,我们可以用CSS过渡替代单向动画,让悬浮和离开状态的切换都保持平滑,同时优化溢出判断逻辑以适配窗口大小变化。
修改后的React组件代码
import { useEffect, useRef, useState } from 'react'; import classes from './test.module.css'; const Test = () => { const textRef = useRef(null); const containerRef = useRef(null); const [isHovered, setIsHovered] = useState(false); const [isOverflowing, setIsOverflowing] = useState(false); // 检查文本是否溢出容器 const checkOverflow = () => { if (!textRef.current || !containerRef.current) return; const textWidth = textRef.current.offsetWidth; const containerWidth = containerRef.current.offsetWidth; setIsOverflowing(textWidth > containerWidth); }; useEffect(() => { checkOverflow(); // 监听窗口大小变化,实时更新溢出状态 window.addEventListener('resize', checkOverflow); return () => window.removeEventListener('resize', checkOverflow); }, []); return ( <div> <div ref={containerRef} className={classes.animated} onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > <h3 className={classes.text} ref={textRef} style={{ // 根据悬浮状态和溢出状态计算位移 transform: isHovered && isOverflowing ? `translateX(calc(${containerRef.current?.offsetWidth}px - ${textRef.current?.offsetWidth}px))` : 'translateX(0)' }} > This is some very very very long text </h3> </div> </div> ); }; export default Test;
修改后的CSS代码
.animated { margin: 200px; position: relative; white-space: nowrap; max-width: 300px; width: 100%; overflow: hidden; background: #0c0c0c; display: inline-block; border: 1px solid white; } .text { color: #fff; display: inline-block; position: relative; /* 统一设置过渡动画,悬浮/离开时自动生效 */ transition: transform 3s linear; }
关键修改说明
- 用CSS过渡替代单向动画:通过
transition属性控制transform的平滑变化,无需定义反向动画,悬浮和离开状态切换时自动触发平滑过渡。 - 精准计算滚动位移:使用
calc(${containerWidth}px - ${textWidth}px)确保文本刚好滚动到容器末尾,不会出现过度滚动。 - 添加窗口resize监听:实时更新溢出状态,避免窗口大小变化后动画失效。
如果你偏好使用@keyframes实现,也可以定义正向和反向两个动画,通过切换类名触发:
可选方案(基于@keyframes)
CSS代码
.animated { margin: 200px; position: relative; white-space: nowrap; max-width: 300px; width: 100%; overflow: hidden; background: #0c0c0c; display: inline-block; border: 1px solid white; } .text { color: #fff; display: inline-block; position: relative; } .scroll-forward { animation: scrollForward 3s linear forwards; } .scroll-back { animation: scrollBack 3s linear forwards; } @keyframes scrollForward { 0% { transform: translateX(0); } 10% { transform: translateX(0); } 90% { transform: translateX(calc(100% - var(--text-width))); } 100% { transform: translateX(calc(100% - var(--text-width))); } } @keyframes scrollBack { 0% { transform: translateX(calc(100% - var(--text-width))); } 100% { transform: translateX(0); } }
React组件中修改类名和样式
<h3 className={`${classes.text} ${ isHovered && isOverflowing ? classes['scroll-forward'] : isOverflowing ? classes['scroll-back'] : '' }`} ref={textRef} style={{ '--text-width': `${textRef.current?.offsetWidth}px` }} > This is some very very very long text </h3>
内容的提问来源于stack exchange,提问作者Cody
相关产品推荐
相关产品推荐

