创建一个组件,实时展示时分秒,并且动态更新数据。
数据变化时利用过渡效果动态更新。
利用两个元素,重叠在一个位置,以达到交替变化的效果
//创建秒显示节点
<div className="text second">
<CSSTransition
in="{renderSecond}"
timeout="{1000}"
classNames="fade"
unmountOnExit="{!renderSecond}"
>
{() =>
<div className="fade">{secondeA}</div>
}
</CSSTransition>
<CSSTransition
in="{!renderSecond}"
timeout="{1000}"
classNames="fade"
unmountOnExit="{renderSecond}"
>
{() =>
<div className="fade">{secondeB}</div>
}
</CSSTransition>
</div>
利用官方提供的过渡动画库react-transition-group
文档地址https://reactcommunity.org/react-transition-group/https://reactcommunity.org/react-transition-group/
使用了CSSTransition组件构建过渡动画
- in<boolean>:用来触发元素enter或exit
- timeout<number>:实现过渡的时间,ms
- classNames<string>:注意是Names,不是Name。组件会依据提供的类名,进行过渡类名的拼接。(classNames='fade'->className='fade fade-enter fade-enter-active')
- unmountOnExit<boolean>:动画结束后是否删除节点
<CSSTransition
in={renderMinute}
timeout={1000}
classNames="fade"
unmountOnExit={!renderMinute}
>
{() => <div className="fade">{minuteA}</div>}
</CSSTransition>
//将两个元素重叠在一个位置
//对类fade-enter,fade-enter-active,fade-exit,fade-exit-active进行动画编写
.text {
position: relative;
width: 25px;
display: flex;
justify-content: center;
align-items: center;
.fade {
position: absolute;
&-enter {
transform: translateY(-20px);
opacity: 0;
&-active {
transform: translateY(0);
opacity: 1;
transition: all 0.8s ease-out;
}
}
&-exit {
transform: translateY(0);
opacity: 0.5;
&-active {
transform: translateY(20px);
opacity: 0;
transition: all 0.6s ease-in;
}
}
}
}
在组件挂载结束后开启定时器,对时间进行更新
//定义两个响应式变量作为秒元素的两个节点
//定义记录当前渲染标记,用来记录显示哪一个元素
//挂载后开启定时器,每一秒都会进行数据更新,根据渲染标记,更新不同的响应式变量,起到新时间替换旧时间的动画效果
const AnimatedText = () => {
const [secondeA, setSecondeA] = useState<string>(dayjs().format('ss'))
const [secondeB, setSecondeB] = useState<string>(dayjs().format('ss'))
const [renderSecond, setRenderSecond] = useState<boolean>(true)
const renderSecondRef = useRef<boolean>(true)
useEffect(() => {
const interval = setInterval(() => {
if (!renderSecondRef.current) {
setSecondeA(dayjs().format('ss'))
} else {
setSecondeB(dayjs().format('ss'))
}
setRenderSecond(a => {
renderSecondRef.current = !a
return !a
})
}, 1000)
return () => clearInterval(interval)
}, [])
}
import { useState, useEffect, useRef } from 'react'
import { CSSTransition } from 'react-transition-group'
import './test.less'
import dayjs from 'dayjs'
const AnimatedText = () => {
const [secondeA, setSecondeA] = useState<string>(dayjs().format('ss'))
const [secondeB, setSecondeB] = useState<string>(dayjs().format('ss'))
const [renderSecond, setRenderSecond] = useState<boolean>(true)
const renderSecondRef = useRef<boolean>(true)
const [minuteA, setMinuteA] = useState<string>(dayjs().format('mm'))
const [minuteB, setMinuteB] = useState<string>(dayjs().format('mm'))
const [renderMinute, setRenderMinute] = useState<boolean>(true)
const renderMinuteRef = useRef<boolean>(true)
const [hourA, setHourA] = useState<string>(dayjs().format('HH'))
const [hourB, setHourB] = useState<string>(dayjs().format('HH'))
const [renderHour, setRenderHour] = useState<boolean>(true)
const renderHourRef = useRef<boolean>(true)
useEffect(() => {
const interval = setInterval(() => {
if (!renderSecondRef.current) {
setSecondeA(dayjs().format('ss'))
} else {
setSecondeB(dayjs().format('ss'))
}
setRenderSecond(a => {
renderSecondRef.current = !a
return !a
})
}, 1000)
return () => clearInterval(interval)
}, [])
useEffect(() => {
const interval = setInterval(() => {
if (dayjs().format('ss') !== '00') return
if (!renderMinuteRef.current) {
setMinuteA(dayjs().format('mm'))
} else {
setMinuteB(dayjs().format('mm'))
}
setRenderMinute(a => {
renderMinuteRef.current = !a
return !a
})
}, 1000)
return () => clearInterval(interval)
}, [])
useEffect(() => {
const interval = setInterval(() => {
if (dayjs().format('mm') !== '00') return
if (!renderHourRef.current) {
setHourA(dayjs().format('HH'))
} else {
setHourB(dayjs().format('HH'))
}
setRenderHour(a => {
renderHourRef.current = !a
return !a
})
}, 1000)
return () => clearInterval(interval)
}, [])
return (
<>
<div className="area">
<div className="text hour">
<CSSTransition
in={renderHour}
timeout={1000}
classNames="fade"
unmountOnExit={!renderHour}
>
{() => <div className="fade">{hourA}</div>}
</CSSTransition>
<CSSTransition
in={!renderHour}
timeout={1000}
classNames="fade"
unmountOnExit={renderHour}
>
{() => <div className="fade">{hourB}</div>}
</CSSTransition>
</div>
<div className="text">:</div>
<div className="text minute">
<CSSTransition
in={renderMinute}
timeout={1000}
classNames="fade"
unmountOnExit={!renderMinute}
>
{() => <div className="fade">{minuteA}</div>}
</CSSTransition>
<CSSTransition
in={!renderMinute}
timeout={1000}
classNames="fade"
unmountOnExit={renderMinute}
>
{() => <div className="fade">{minuteB}</div>}
</CSSTransition>
</div>
<div className="text">:</div>
<div className="text second">
<CSSTransition
in={renderSecond}
timeout={1000}
classNames="fade"
unmountOnExit={!renderSecond}
>
{() => <div className="fade">{secondeA}</div>}
</CSSTransition>
<CSSTransition
in={!renderSecond}
timeout={1000}
classNames="fade"
unmountOnExit={renderSecond}
>
{() => <div className="fade">{secondeB}</div>}
</CSSTransition>
</div>
</div>
</>
)
}
export default AnimatedText
.area {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
.text {
position: relative;
width: 25px;
display: flex;
justify-content: center;
align-items: center;
.fade {
position: absolute;
&-enter {
transform: translateY(-20px);
opacity: 0;
&-active {
transform: translateY(0);
opacity: 1;
transition: all 0.8s ease-out;
}
}
&-exit {
transform: translateY(0);
opacity: 0.5;
&-active {
transform: translateY(20px);
opacity: 0;
transition: all 0.6s ease-in;
}
}
}
}
}
标签:const,fade,dayjs,format,展示,React,useState,过渡,return From: https://www.cnblogs.com/karle/p/18325906