未验证 提交 39077e2b 编写于 作者: _ __Oasis__ 提交者: GitHub

Merge pull request #841 from irisSong/nutui-react

feat: animatingNumbers组件countUp特效开发完成
...@@ -432,6 +432,16 @@ ...@@ -432,6 +432,16 @@
"sort": 4, "sort": 4,
"show": true, "show": true,
"author": "lzz" "author": "lzz"
},
{
"version": "1.0.0",
"name": "AnimatingNumbers",
"type": "component",
"cName": "数字动画",
"desc": "带特效的数字",
"sort": 7,
"show": true,
"author": "songsong"
} }
] ]
}, },
......
import React, { FunctionComponent, Component } from 'react'
import './animatingnumbers.scss'
import { CountUp } from './countup'
export interface AnimatingNumbersProps {}
const defaultProps = {} as AnimatingNumbersProps
type AnimatingNumbersStates = {}
export class AnimatingNumbers extends Component<AnimatingNumbersProps, AnimatingNumbersStates> {
static defaultProps = defaultProps
static displayName = 'NutAnimatingNumbers'
static CountUp = CountUp
constructor(props: AnimatingNumbersProps) {
super(props)
this.state = {}
}
render() {
return <div className="nut-animatingnumbers"></div>
}
}
.nut-countup {
&__list {
display: inline-flex;
height: 32px;
overflow: hidden;
}
&__listitem {
height: 32px;
overflow: hidden;
font-size: 18px;
color: #000;
font-weight: bold;
}
&__number,
&__separator {
display: flex;
flex-direction: column;
align-items: center;
span {
height: 32px;
line-height: 32px;
}
}
}
// 自定义样式
.custom-coutup {
.nut-countup__listitem--number {
margin: 0 1px;
border-radius: 4px;
color: #fff;
background-color: #031f63;
}
.nut-countup__number {
width: 24px;
}
}
import React, { CSSProperties, FunctionComponent, useEffect, useRef, useState } from 'react'
import './countup.scss'
import bem from '@/utils/bem'
export interface CountUpProps {
maxLen: number
endNumer: string
delaySpeed?: number
easeSpeed: number
thousands: boolean
className: string
style: React.CSSProperties
}
const defaultProps = {
maxLen: 0,
endNumer: '',
delaySpeed: 300,
easeSpeed: 1,
thousands: false,
className: '',
} as CountUpProps
export const CountUp: FunctionComponent<Partial<CountUpProps>> = (props) => {
const { maxLen, endNumer, delaySpeed, easeSpeed, className, thousands, ...reset } = {
...defaultProps,
...props,
}
const b = bem('countup')
const countupRef = useRef<HTMLDivElement>(null)
const timerRef = useRef(0)
const numbers = Array.from({ length: 10 }).map((item, index) => {
return index
})
const getShowNumber = () => {
const splitArr = endNumer.split('.')
const intNumber =
maxLen && splitArr[0].length < maxLen
? (Array(maxLen).join('0') + splitArr[0]).slice(-maxLen)
: splitArr[0]
const currNumber = `${
thousands ? intNumber.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') : intNumber
}${splitArr[1] ? '.' : ''}${splitArr[1] || ''}`
return currNumber.split('')
}
const numerArr = getShowNumber()
const setNumberTransform = () => {
if (countupRef.current) {
const numberItems = countupRef.current.querySelectorAll('.nut-countup__number')
const numberFilterArr: Array<string> = numerArr.filter((item: any) => !isNaN(item))
for (let [index] of Object.entries(numberItems)) {
const elem = numberItems[Number(index)] as HTMLElement
const idx = Number(numberFilterArr[Number(index)])
if ((idx || idx == 0) && elem) {
const transform = `translate(0, -${(idx == 0 ? 10 : idx) * 5}%)`
elem.style.transform = transform
elem.style.webkitTransform = transform
}
}
}
}
const numberEaseStyle: CSSProperties = {
transition: `transform ${easeSpeed}s ease-in-out`,
}
useEffect(() => {
timerRef.current = window.setTimeout(() => {
setNumberTransform()
}, delaySpeed)
return () => {
window.clearTimeout(timerRef.current)
}
}, [])
useEffect(() => {
setNumberTransform()
}, [numerArr])
return (
<div className={`${b()} ${className}`} ref={countupRef}>
<ul className={b('list')}>
{numerArr.map((item: any, idx: number) => {
return (
<li className={`${b('listitem', { number: !isNaN(item) ? true : false })}`} key={idx}>
{!isNaN(item) ? (
<span className={b('number')} style={numberEaseStyle}>
{[...numbers, ...numbers].map((number, subidx) => {
return <span key={subidx}>{number}</span>
})}
</span>
) : (
<span className={b('separator')}>{item}</span>
)}
</li>
)
})}
</ul>
</div>
)
}
CountUp.defaultProps = defaultProps
CountUp.displayName = 'NutCountUp'
import React, { useEffect, useState } from 'react'
import { AnimatingNumbers } from './animatingnumbers'
const AnimatingNumbersDemo = () => {
const [endNumer, setEndNumer] = useState('1570.99')
useEffect(() => {
setInterval(() => {
setEndNumer(`${Math.floor(Math.random() * 999999)}.${Math.floor(Math.random() * 89 + 10)}`)
}, 30000)
}, [])
return (
<>
<div className="demo">
<h2>CountUp-基础用法</h2>
<AnimatingNumbers.CountUp endNumer="678.94" />
<h2>CountUp-自定义样式,动态修改数据(需要指定最大位数)</h2>
<AnimatingNumbers.CountUp
endNumer={endNumer}
easeSpeed={1.2}
maxLen={6}
className="custom-coutup"
/>
</div>
</>
)
}
export default AnimatingNumbersDemo
# AnimatingNumbers组件
### 介绍
基于 xxxxxxx
### 安装
## 代码演示
### 基础用法1
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| name | 图标名称或图片链接 | String | - |
| color | 图标颜色 | String | - |
| size | 图标大小,如 '20px' '2em' '2rem' | String | - |
| class-prefix | 类名前缀,用于使用自定义图标 | String | 'nutui-iconfont' |
| tag | HTML 标签 | String | 'i' |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| click | 点击图标时触发 | event: Event |
import { AnimatingNumbers } from './animatingnumbers'
import { CountUp } from './countup'
AnimatingNumbers.CountUp = CountUp
export default AnimatingNumbers
...@@ -27,6 +27,7 @@ import Uploader from './uploader' ...@@ -27,6 +27,7 @@ import Uploader from './uploader'
import Input from './input' import Input from './input'
import TextArea from './textarea' import TextArea from './textarea'
import CheckBox from './checkbox' import CheckBox from './checkbox'
import AnimatingNumbers from './animatingnumbers'
import Tag from './tag' import Tag from './tag'
import Badge from './badge' import Badge from './badge'
import Signature from './signature' import Signature from './signature'
...@@ -61,6 +62,7 @@ export { ...@@ -61,6 +62,7 @@ export {
Input, Input,
TextArea, TextArea,
CheckBox, CheckBox,
AnimatingNumbers,
Tag, Tag,
Badge, Badge,
Signature, Signature,
......
...@@ -23,7 +23,7 @@ const clear = () => { ...@@ -23,7 +23,7 @@ const clear = () => {
img.remove() img.remove()
} }
} }
Signature confirm={confirm} clear={clear}></Signature> <Signature confirm={confirm} clear={clear}></Signature>
<p className="demo-tips demo1" style={demoStyles}> <p className="demo-tips demo1" style={demoStyles}>
Tips: 点击确认按钮,下方显示签名图片 Tips: 点击确认按钮,下方显示签名图片
</p> </p>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册