4. 完善组件
支持多位数
- 将传入数字拆分为一个数组;
- 将数组渲染为多个
<NumberScrollItem />
; - 将参数
value
绑定至 data-value
。
const NumberScroll = (props) => {
const numbers = String(props.number).split('')
return (
<div className="number-scroll">
{numbers.map((item) => (
<NumberScrollItem key={uuidV4()} value={+item} />
))}
</div>
)
}
const NumberScrollItem = (props) => {
return (
<div className="number-scroll__stage" ref={ref}>
<div className="number-scroll__gimmick" data-value={props.value}>
{}
</div>
</div>
)
}
支持负数、浮点数、千分位数字
- 新建组件
SymbolItem
用于显示符号; - 添加判断数字的方法;
- 条件渲染不同的组件。
const SymbolItem = (props) => {
const { value } = props
return (
<div className="number-scroll__stage">
<div className="number-scroll__gimmick ">{value}</div>
</div>
)
}
const isNumber = (value) => /^\d$/g.test(value)
const NumberScroll = (props) => {
return (
<div className="number-scroll">
{numbers.map((item) =>
isNumber(item) ? (
<NumberScrollItem key={uuidV4()} value={+item} />
) : (
<SymbolItem key={uuidV4()} value={item} />
)
)}
</div>
)
}
支持在传入数字改变时重新滚动
- 将
useNumberScroll
从 <NumberScrollItem />
提升至 <NumberScroll />
(避免 props.number
更改时,某位数的值和更改前一样,导致个别数字没有触发动画); - 将
props.number
作为触发动画的依赖项; - 为
<NumberScrollItem />
添加一个 className
以区分数字和符号; - 传给
gsap.fromTo
的选择器只选择类型为数字的子项,使用 ctx.targets().forEach()
逐个为选中的元素添加结尾动画。
const NumberScroll = (props) => {
const ref = useNumberScroll(
{
duration: props.duration,
},
[props.number]
)
return (
<div className="number-scroll" ref={ref}>
{}
</div>
)
}
const NumberScrollItem = (props) => {
return (
<div className="number-scroll__stage">
<div
className="number-scroll__gimmick number-scroll__gimmick--scroll"
data-value={props.value}
style={{
transform: `translateY(-${props.value * HEIGHT_PER_NUMBER}px)`,
}}
>
{}
</div>
</div>
)
}
const endAnimate = (ctx) => {
ctx.targets().forEach((ele) => {
const value = +ele.dataset.value
})
}
const animate = () => {
const gimmicSelector = '.number-scroll__gimmick--scroll'
gsap
.fromTo
()
}