React如何实现选中条带平滑滑动动画的Tab选项卡
Tab选中指示条平滑滑动改造方案
你当前的实现通过固定left/right类切换指示条位置,既没有过渡动画逻辑,也只能适配2个固定宽度的Tab,按以下步骤改造即可实现丝滑的滑动效果:
给指示条添加CSS过渡属性
动画的核心是给指示条加上状态变化的过渡规则,在.selector样式中添加以下代码:.selector { position: absolute; bottom: 0; height: 2px; background: #1677ff; z-index: 1; /* 控制滑动动画的时长、缓动曲线,可根据需求调整参数 */ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); }注意承载Tab和指示条的父容器必须设置
position: relative,否则指示条绝对定位会出现偏移。替换硬编码类名逻辑,动态计算指示条位置
去掉原来tab === "two" ? "right" : "left"的固定判断,通过DOM属性获取选中Tab的实际偏移量和宽度,动态给指示条赋值样式,不管Tab数量多少、文字长度是否一致都能适配。React环境下核心实现代码如下:import { useState, useRef, useEffect } from 'react'; export default function Tabs() { const [activeTab, setActiveTab] = useState('one'); // 存储每个Tab项的DOM引用 const tabRefs = useRef({}); // 存储指示条的动态样式 const [indicatorStyle, setIndicatorStyle] = useState({ left: 0, width: 0 }); // 选中Tab变化时,更新指示条位置 useEffect(() => { const currentTabNode = tabRefs.current[activeTab]; if (currentTabNode) { setIndicatorStyle({ left: currentTabNode.offsetLeft, width: currentTabNode.offsetWidth }); } }, [activeTab]); // 组件首次挂载时初始化指示条位置 useEffect(() => { const initialTabNode = tabRefs.current[activeTab]; if (initialTabNode) { setIndicatorStyle({ left: initialTabNode.offsetLeft, width: initialTabNode.offsetWidth }); } }, []); // 示例Tab配置,可按需扩展 const tabConfig = [ { key: 'one', label: '第一个Tab' }, { key: 'two', label: '第二个Tab' }, { key: 'three', label: '第三个长文本Tab' } ]; return ( <div className="tabs-wrapper" style={{ position: 'relative' }}> <div className="tab-nav"> {tabConfig.map(tab => ( <div key={tab.key} ref={node => (tabRefs.current[tab.key] = node)} className={`tab-item ${activeTab === tab.key ? 'active' : ''}`} onClick={() => setActiveTab(tab.key)} style={{ padding: '12px 16px', cursor: 'pointer' }} > {tab.label} </div> ))} </div> {/* 指示条直接绑定动态计算的样式,不再依赖固定类名 */} <div className="selector" style={indicatorStyle}></div> </div> ); }补充响应式适配(可选)
如果你的页面需要适配不同屏幕尺寸,在窗口大小变化时Tab宽度可能发生改变,可以加resize事件监听,触发时重新计算指示条位置,避免错位:useEffect(() => { const recalcIndicatorPos = () => { const currentTabNode = tabRefs.current[activeTab]; if (currentTabNode) { setIndicatorStyle({ left: currentTabNode.offsetLeft, width: currentTabNode.offsetWidth }); } }; window.addEventListener('resize', recalcIndicatorPos); return () => window.removeEventListener('resize', recalcIndicatorPos); }, [activeTab]);
如果需要调整动画手感,直接修改.selector上transition属性的时长和缓动函数即可:比如将时长改为0.2s动画会更干脆,改为0.5s会更柔和。
内容的提问来源于stack exchange,提问作者Jenny Le
相关产品推荐
相关产品推荐

