前端添加动画一般都会在css中使用@keyframes定义一个动画名称,然后使用animation
.content {
width: 40px;
height: 40px;
margin-top: 40px;
background-color: rgb(114, 170, 151);
animation: normalAnima 1.8s linear infinite;
}
@keyframes normalAnima {
100% { transform: rotate(360deg); }
}
然后在对应的dom中添加相应的类名就可以了
现在我们需要动态的添加上动画效果
一,通过动态style添加动画
把content中的animation去掉,然后在dom上添加style属性
import React, { useRef, useState } from 'react';
import { Button } from 'antd';
import './NormalAnima.less';
const NormalAnima: React.FC = () => {
const animaDom = useRef<HTMLDivElement>(null!);
const [btnText2, setBtnText2] = useState('开始');
const [animaStyle2, setAnimaStyle2] = useState<React.CSSProperties>({})
const changeAnimaStatus2 = () => {
if (btnText2 === '开始') {
setAnimaStyle({animation: 'normalAnima 1.8s linear infinite'});
setBtnText2('停止');
} else {
setAnimaStyle({});
setBtnText2('开始');
}
}
return (
<div className={styles.root}>
<Button onClick={changeAnimaStatus2}>{btnText2}</Button>
<div className={styles.animaContainer}>
<div className={styles.content} style={animaStyle}></div>
</div>
</div>
)
}
export default NormalAnima;
在一些框架中,比如umi,可以按照下列方式导入样式表
import styles from './NormalAnima.less';
如果是这样的话,那么上面代码的第13行就是不行的,动画不会生效,具体原因我们可以打印输出styles查看
可以看到,我们使用@keyframes定义的动画也被模块化命名了,因此第十三行需要改成
setAnimaStyle({animation: `${styles.normalAnima} 1.8s linear infinite`});
二,通过动态添加类名增加动画效果
单独写一个记录动画效果的类名
.content {
width: 40px;
height: 40px;
margin-top: 40px;
background-color: rgb(114, 170, 151);
}
.contentRotate {
animation: normalAnima 1.8s linear infinite;
}
在需要的时候添加上该类名即可
const animaDom = useRef<HTMLDivElement>(null!);
const [btnText1, setBtnText1] = useState('开始');
···
const changeAnimaStatus1 = () => {
if (btnText1 === '开始') {
animaDom.current.classList.add(styles.contentRotate);
setBtnText1('停止');
} else {
animaDom.current.classList.remove(styles.contentRotate);
setBtnText1('开始');
}
}
···
<Button onClick={changeAnimaStatus1}>{btnText1}</Button>
<div className={styles.animaContainer}>
<div className={styles.content} ref={animaDom}></div>
</div>
三,通过animation-play-status控制动画
上述两个方法都有一个比较明显的缺点,就是无法控制动画的暂停状态,而使用animation-play-status不仅可以很好的解决这个问题,而且就原理来说也会更加简单,所有三种方法的完整代码
import React, { useRef, useState } from 'react';
import { Button } from 'antd';
import styles from './NormalAnima.less';
const NormalAnima: React.FC = () => {
const animaDom = useRef<HTMLDivElement>(null!);
const [btnText1, setBtnText1] = useState('开始');
const [btnText2, setBtnText2] = useState('开始');
const [btnText3, setBtnText3] = useState('开始');
const [animaStyle, setAnimaStyle] = useState<React.CSSProperties>({})
const [animaStyle2, setAnimaStyle2] = useState<React.CSSProperties>({})
const changeAnimaStatus1 = () => {
if (btnText1 === '开始') {
animaDom.current.classList.add(styles.contentRotate);
setBtnText1('停止');
} else {
animaDom.current.classList.remove(styles.contentRotate);
setBtnText1('开始');
}
}
const changeAnimaStatus2 = () => {
if (btnText2 === '开始') {
setAnimaStyle({animation: `${styles.normalAnima} 1.8s linear infinite`});
setBtnText2('停止');
} else {
setAnimaStyle({});
setBtnText2('开始');
}
}
const changeAnimaStatus3 = () => {
if (btnText3 === '开始') {
setAnimaStyle2({animationPlayState: 'paused'});
setBtnText3('暂停');
} else {
setAnimaStyle2({animationPlayState: 'running'});
setBtnText3('开始');
}
}
return (
<div className={styles.root}>
<Button onClick={changeAnimaStatus1}>{btnText1}</Button>
<div className={styles.animaContainer}>
<div className={styles.content} ref={animaDom}></div>
</div>
<Button onClick={changeAnimaStatus2}>{btnText2}</Button>
<div className={styles.animaContainer}>
<div className={styles.content} style={animaStyle}></div>
</div>
<Button onClick={changeAnimaStatus3}>{btnText3}</Button>
<div className={styles.animaContainer}>
<div className={`${styles.content} ${styles.contentRotate}`} style={animaStyle2}></div>
</div>
</div>
)
}
export default NormalAnima;
页面效果