Framer Motion退出动画绕非中心轴旋转,元素偏移问题求助
问题解决思路及代码修复
问题根源
- 两个独立的
AnimatePresence容器无法同步控制图标的进入/退出动画,导致切换时序错乱 - 旋转原点(
origin)设置不一致且未固定,加上没有给容器固定尺寸,旋转时触发布局重排造成偏移 exit动画参数设置错误,未实现"旋转消失"效果,反而让元素停留在原位引发布局冲突
修复后的代码
import { useAppDispatch, useAppSelector } from '@/redux/hooks'; import { updateShowMore } from '@/slices/navigation.slice'; import React from 'react'; import { BsJustify } from 'react-icons/bs'; import { MdOutlineClose } from 'react-icons/md'; import classes from './ViewIcon.module.css'; import { motion, AnimatePresence } from 'framer-motion'; export default function ViewIcon() { const { showMore } = useAppSelector((state) => state.navigation); const dispatch = useAppDispatch(); const toggleResults = (value: boolean) => dispatch(updateShowMore(value)); return ( <div style={{ width: '24px', height: '24px', position: 'relative' }}> <AnimatePresence mode="wait"> {showMore ? ( <motion.div key="close-icon" initial={{ rotateZ: -180, opacity: 0 }} animate={{ rotateZ: 0, opacity: 1 }} exit={{ rotateZ: 180, opacity: 0 }} style={{ origin: 'center', position: 'absolute', inset: 0 }} > <MdOutlineClose className={classes.ShowMore} onClick={() => toggleResults(false)} /> </motion.div> ) : ( <motion.div key="menu-icon" initial={{ rotateZ: 180, opacity: 0 }} animate={{ rotateZ: 0, opacity: 1 }} exit={{ rotateZ: -180, opacity: 0 }} style={{ origin: 'center', position: 'absolute', inset: 0 }} > <BsJustify className={classes.ShowMore} onClick={() => toggleResults(true)} /> </motion.div> )} </AnimatePresence> </div> ); }
关键改动说明
- 合并
AnimatePresence容器:将两个图标放在同一个容器中,通过mode="wait"控制动画时序(若需要同时切换可去掉该属性),确保动画同步 - 固定容器尺寸+绝对定位:父容器设置固定宽高,图标用绝对定位铺满容器,避免切换时触发布局重排,彻底解决偏移问题
- 统一旋转原点:设置
origin: 'center',让图标围绕中心旋转,消除因原点偏移导致的位置变化 - 调整动画参数:
exit时添加旋转+透明度变化实现"旋转消失",进入动画对应反向旋转+淡入,达成无缝切换效果
内容的提问来源于stack exchange,提问作者Shivam Sahil
相关产品推荐
相关产品推荐

