React中MouseEnter与MouseLeave动画无法实现的问题求助
解决React Material-UI媒体卡片的平滑动画问题
嘿,别担心代码杂乱,新手摸索过程中有点混乱太正常啦!你的鼠标事件能正常触发,但动画没达到平滑效果,主要是缺少CSS过渡配置,还有几个小细节需要调整,咱们一步步来修复:
核心问题分析
- 没有添加过渡(transition)属性:状态变化时没有指定过渡时长和缓动逻辑,元素会瞬间切换状态,自然没有平滑动画。
makeStyles无法响应组件内state变化:makeStyles的样式是在组件初始化时生成的,后续state更新不会重新计算这些样式,所以像scale: imgSize这种写法根本不会生效。- 状态值的类型和写法错误:比如
areaHeight初始是数字100,后来改成字符串'100%',单位不统一;textPosition里的!important完全没必要,React内联样式不需要这个语法。
修改后的完整代码
import React, { useState } from 'react'; import { makeStyles } from '@material-ui/core/styles'; import CardActionArea from '@material-ui/core/CardActionArea'; import CardContent from '@material-ui/core/CardContent'; import CardMedia from '@material-ui/core/CardMedia'; import Typography from '@material-ui/core/Typography'; import Grid from '@material-ui/core/Grid'; import Paper from '@material-ui/core/Paper'; export default function SectionCard(props) { const [areaHeight, setAreaHeight] = useState('100px'); const [imgScale, setImgScale] = useState(1); const [lineColor, setLineColor] = useState('dodgerblue'); const [textPaddingTop, setTextPaddingTop] = useState(0); const useStyles = makeStyles((theme) => ({ root: { maxWidth: 345, position: 'relative', // 给父元素加相对定位,确保遮罩层的绝对定位生效 overflow: 'hidden', // 避免图片缩放时超出卡片容器 }, media: { height: 400, transition: 'transform 0.3s ease', // 图片缩放的过渡效果 }, greyCover: { backgroundColor: 'rgba(0, 0, 0, 0.5)', width: '100%', bottom: 0, position: 'absolute', transition: 'height 0.3s ease', // 遮罩层高度变化的过渡效果 }, line: { height: 5, width: '100%', borderRadius: 0, transition: 'background-color 0.3s ease', // 线条颜色变化的过渡效果 }, cardText: { fontFamily: 'Quicksand !important', color: 'white !important', transition: 'padding-top 0.3s ease', // 文本位置变化的过渡效果 }, })); const classes = useStyles(); const handleMouseEnter = () => { setAreaHeight('100%'); setLineColor('red'); setImgScale(1.2); setTextPaddingTop(150); }; const handleMouseLeave = () => { setAreaHeight('100px'); setLineColor('dodgerblue'); setImgScale(1); setTextPaddingTop(0); }; return ( <Grid item xs={12} sm={4}> <CardActionArea className={classes.root} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}> <CardMedia className={classes.media} image={props.img} style={{ transform: `scale(${imgScale})` }} // 动态缩放用内联样式,响应state变化 /> <CardContent className={classes.greyCover} style={{ height: areaHeight }} // 动态高度用内联样式 > <div className={classes.cardText} style={{ paddingTop: `${textPaddingTop}px` }}> <Typography gutterBottom variant="h5" component="h2" align="center"> {props.title} </Typography> <Typography component="p" align="center"> {props.text} </Typography> </div> </CardContent> </CardActionArea> <Paper className={classes.line} style={{ backgroundColor: lineColor }} /> {/* 动态颜色用内联样式 */} </Grid> ); }
关键修改点说明
- 添加过渡效果:给所有需要动画的元素(遮罩、图片、线条、文本)都加上了
transition属性,指定了0.3秒的过渡时长和自然的缓动函数,让状态变化更平滑。 - 动态样式移至内联
style:makeStyles生成的类是静态的,无法响应state更新,所以把图片缩放、遮罩高度、线条颜色这些动态样式放到元素的style属性里,确保状态变化时样式能实时更新。 - 统一状态值类型:把
areaHeight初始值改成'100px',和'100%'保持字符串类型,避免单位混乱导致的过渡异常。 - 优化卡片容器:给
root类添加overflow: hidden,避免图片缩放时超出卡片边界,视觉效果更整洁。 - 拆分事件处理:把原来逗号分隔的setState拆成单独的函数调用,代码更清晰易维护。
现在你再试试,鼠标悬停时灰色遮罩会平滑展开到全屏,图片慢慢放大,线条颜色渐变,文本也能平滑上移到中部啦!
内容的提问来源于stack exchange,提问作者Melih Bektas
相关产品推荐
相关产品推荐

