-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(components): 新增 NumberTransition 数值动画组件
- Loading branch information
1 parent
614ecef
commit a56c193
Showing
18 changed files
with
454 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,3 +17,4 @@ | |
@import './collapse'; | ||
@import './option'; | ||
@import './dropdown'; | ||
@import './number-transition'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
packages/components/src/number-transition/NumberTransition.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React, { useEffect, useRef } from 'react'; | ||
import type { NumberTransitionProps } from './number-transition.types'; | ||
import { getComponentClass, useForceUpdate } from '@pkg/shared'; | ||
import type { RequiredPart } from '@tool-pack/types'; | ||
import { createTimeCountDown, getClassNames } from '@tool-pack/basic'; | ||
import { animateTo } from '@tool-pack/dom'; | ||
|
||
const rootName = getComponentClass('number-transition'); | ||
const defaultProps = { | ||
duration: 3000, | ||
from: 0, | ||
to: 10, | ||
precision: 0, | ||
timingFunction: 'ease', | ||
format: (value) => value, | ||
} satisfies Partial<NumberTransitionProps>; | ||
|
||
export const NumberTransition: React.FC<NumberTransitionProps> = | ||
React.forwardRef<HTMLDivElement, NumberTransitionProps>((props, ref) => { | ||
const { | ||
duration, | ||
active, | ||
precision, | ||
from, | ||
to, | ||
resetSignal, | ||
timingFunction, | ||
format, | ||
onFinished, | ||
attrs, | ||
} = props as RequiredPart<NumberTransitionProps, keyof typeof defaultProps>; | ||
|
||
const valueRef = useRef<number | string>(from); | ||
const cancelerRef = useRef<() => void>(); | ||
const durationRef = useRef(duration); | ||
const signalRef = useRef(resetSignal); | ||
const forceUpdate = useForceUpdate(); | ||
|
||
const reset = () => { | ||
cancelerRef.current?.(); | ||
valueRef.current = from; | ||
durationRef.current = duration; | ||
}; | ||
|
||
useEffect(() => { | ||
if (!resetSignal === signalRef.current) return; | ||
signalRef.current = resetSignal; | ||
reset(); | ||
forceUpdate(); | ||
}, [resetSignal]); | ||
|
||
useEffect(() => { | ||
if (!active || durationRef.current <= 0) return; | ||
cancelerRef.current?.(); | ||
|
||
const initValue = Number(valueRef.current); | ||
const countDown = createTimeCountDown(durationRef.current); | ||
|
||
const getValue: (value: number) => number | string = | ||
precision === null | ||
? (v) => v | ||
: precision === 0 | ||
? (v) => Math.floor(v) | ||
: (v) => v.toFixed(precision); | ||
|
||
const { stop } = animateTo({ | ||
timeout: durationRef.current, | ||
from: initValue, | ||
to, | ||
timingFn: timingFunction, | ||
callback: (num) => { | ||
valueRef.current = getValue(num); | ||
forceUpdate(); | ||
}, | ||
after: onFinished, | ||
}); | ||
return (cancelerRef.current = () => { | ||
durationRef.current = countDown(); | ||
countDown.pause(); | ||
stop(); | ||
cancelerRef.current = undefined; | ||
}); | ||
}, [active, from, duration, timingFunction, to, precision]); | ||
|
||
return ( | ||
<div | ||
{...attrs} | ||
ref={ref} | ||
className={getClassNames(rootName, attrs?.className)}> | ||
{format(valueRef.current)} | ||
</div> | ||
); | ||
}); | ||
|
||
NumberTransition.defaultProps = defaultProps; | ||
NumberTransition.displayName = 'NumberTransition'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* title: 基础用法 | ||
* description: NumberTransition 基础用法。 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { Button, NumberTransition, Space } from '@tool-pack/react-ui'; | ||
|
||
const App: React.FC = () => { | ||
const [active, setActive] = useState(false); | ||
const [disabled, setDisabled] = useState(false); | ||
|
||
return ( | ||
<Space vertical> | ||
<Space> | ||
<Button | ||
type="primary" | ||
disabled={disabled} | ||
onClick={() => setActive((v) => !v)}> | ||
{active ? '暂停' : '启动'} | ||
</Button> | ||
</Space> | ||
<NumberTransition | ||
active={active} | ||
from={30} | ||
to={50} | ||
onFinished={() => { | ||
setDisabled(true); | ||
setActive(false); | ||
}} | ||
/> | ||
</Space> | ||
); | ||
}; | ||
|
||
export default App; |
36 changes: 36 additions & 0 deletions
36
packages/components/src/number-transition/demo/duration.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* title: 动画时长 | ||
* description: 自定义动画时长,单位为毫秒。默认为 3000。 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { Button, NumberTransition, Space } from '@tool-pack/react-ui'; | ||
|
||
const App: React.FC = () => { | ||
const [active, setActive] = useState(false); | ||
const [disabled, setDisabled] = useState(false); | ||
|
||
return ( | ||
<Space vertical> | ||
<Space> | ||
<Button | ||
type="primary" | ||
disabled={disabled} | ||
onClick={() => setActive((v) => !v)}> | ||
{active ? '暂停' : '启动'} | ||
</Button> | ||
</Space> | ||
<NumberTransition | ||
active={active} | ||
duration={8000} | ||
to={25} | ||
onFinished={() => { | ||
setDisabled(true); | ||
setActive(false); | ||
}} | ||
/> | ||
</Space> | ||
); | ||
}; | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* title: 格式化 | ||
* description: 对数字显示格式化。 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { Button, NumberTransition, Space } from '@tool-pack/react-ui'; | ||
|
||
const format = new Intl.NumberFormat('zh-Hans-CN-u-nu-hanidec'); | ||
|
||
const App: React.FC = () => { | ||
const [active, setActive] = useState(false); | ||
const [disabled, setDisabled] = useState(false); | ||
|
||
return ( | ||
<Space vertical> | ||
<Space> | ||
<Button | ||
type="primary" | ||
disabled={disabled} | ||
onClick={() => setActive((v) => !v)}> | ||
{active ? '暂停' : '启动'} | ||
</Button> | ||
</Space> | ||
<NumberTransition | ||
active={active} | ||
to={50} | ||
format={(value) => { | ||
return format.format(Number(value)); | ||
}} | ||
onFinished={() => { | ||
setDisabled(true); | ||
setActive(false); | ||
}} | ||
/> | ||
</Space> | ||
); | ||
}; | ||
|
||
export default App; |
49 changes: 49 additions & 0 deletions
49
packages/components/src/number-transition/demo/precision.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* title: 精度 | ||
* description: 小数位数。默认小数位数为 0。为 null 时保持原样输出。 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { Button, NumberTransition, Space } from '@tool-pack/react-ui'; | ||
|
||
const App: React.FC = () => { | ||
const [active, setActive] = useState(false); | ||
const [disabled, setDisabled] = useState(false); | ||
|
||
return ( | ||
<Space vertical> | ||
<Space> | ||
<Button | ||
type="primary" | ||
disabled={disabled} | ||
onClick={() => setActive((v) => !v)}> | ||
{active ? '暂停' : '启动'} | ||
</Button> | ||
</Space> | ||
<Space> | ||
<div>小数位 2</div> | ||
<NumberTransition | ||
active={active} | ||
precision={2} | ||
onFinished={() => { | ||
setDisabled(true); | ||
setActive(false); | ||
}} | ||
/> | ||
</Space> | ||
<Space> | ||
<div>小数位 null 保持原样</div> | ||
<NumberTransition | ||
active={active} | ||
precision={null} | ||
onFinished={() => { | ||
setDisabled(true); | ||
setActive(false); | ||
}} | ||
/> | ||
</Space> | ||
</Space> | ||
); | ||
}; | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* title: 重置 | ||
* description: 重置为初始状态。 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { Button, NumberTransition, Space } from '@tool-pack/react-ui'; | ||
|
||
const App: React.FC = () => { | ||
const [active, setActive] = useState(false); | ||
const [disabled, setDisabled] = useState(false); | ||
const [signal, setSignal] = useState({}); | ||
|
||
const reset = () => { | ||
setDisabled(false); | ||
setActive(false); | ||
setSignal({}); | ||
}; | ||
|
||
const onFinished = () => { | ||
setDisabled(true); | ||
setActive(false); | ||
}; | ||
|
||
return ( | ||
<Space vertical> | ||
<Space> | ||
<Button | ||
type="primary" | ||
disabled={disabled} | ||
onClick={() => setActive((v) => !v)}> | ||
{active ? '暂停' : '启动'} | ||
</Button> | ||
<Button onClick={reset}>重置</Button> | ||
</Space> | ||
<NumberTransition | ||
resetSignal={signal} | ||
active={active} | ||
to={50} | ||
onFinished={onFinished} | ||
/> | ||
</Space> | ||
); | ||
}; | ||
|
||
export default App; |
Oops, something went wrong.