diff --git a/src/config.json b/src/config.json index c7217a876b4eee7688dee39b4e158d3cde162855..0d73e898f0ddc3313b7fb867ec97b8fdbdbf7e4b 100644 --- a/src/config.json +++ b/src/config.json @@ -432,6 +432,16 @@ "sort": 4, "show": true, "author": "lzz" + }, + { + "version": "1.0.0", + "name": "AnimatingNumbers", + "type": "component", + "cName": "数字动画", + "desc": "带特效的数字", + "sort": 7, + "show": true, + "author": "songsong" } ] }, diff --git a/src/packages/animatingnumbers/animatingnumbers.scss b/src/packages/animatingnumbers/animatingnumbers.scss new file mode 100644 index 0000000000000000000000000000000000000000..cf8cf84eb5cf391a72bb842e6f2ad90b39ce65d5 --- /dev/null +++ b/src/packages/animatingnumbers/animatingnumbers.scss @@ -0,0 +1,2 @@ +.nut-animatingnumbers { +} diff --git a/src/packages/animatingnumbers/animatingnumbers.tsx b/src/packages/animatingnumbers/animatingnumbers.tsx new file mode 100644 index 0000000000000000000000000000000000000000..82962ad38e532bab00c113276bd510b07b00fc96 --- /dev/null +++ b/src/packages/animatingnumbers/animatingnumbers.tsx @@ -0,0 +1,22 @@ +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 { + static defaultProps = defaultProps + static displayName = 'NutAnimatingNumbers' + static CountUp = CountUp + constructor(props: AnimatingNumbersProps) { + super(props) + this.state = {} + } + + render() { + return
+ } +} diff --git a/src/packages/animatingnumbers/countup.scss b/src/packages/animatingnumbers/countup.scss new file mode 100644 index 0000000000000000000000000000000000000000..f9df96b9f6e432de65e7d03ba2728e4982e70188 --- /dev/null +++ b/src/packages/animatingnumbers/countup.scss @@ -0,0 +1,36 @@ +.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; + } +} diff --git a/src/packages/animatingnumbers/countup.tsx b/src/packages/animatingnumbers/countup.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6942e82abfb27ae9ce694add2973314186ad4bfc --- /dev/null +++ b/src/packages/animatingnumbers/countup.tsx @@ -0,0 +1,105 @@ +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> = (props) => { + const { maxLen, endNumer, delaySpeed, easeSpeed, className, thousands, ...reset } = { + ...defaultProps, + ...props, + } + const b = bem('countup') + const countupRef = useRef(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 = 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 ( +
+
    + {numerArr.map((item: any, idx: number) => { + return ( +
  • + {!isNaN(item) ? ( + + {[...numbers, ...numbers].map((number, subidx) => { + return {number} + })} + + ) : ( + {item} + )} +
  • + ) + })} +
+
+ ) +} + +CountUp.defaultProps = defaultProps +CountUp.displayName = 'NutCountUp' diff --git a/src/packages/animatingnumbers/demo.tsx b/src/packages/animatingnumbers/demo.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a4fbd8933c068d37fec9c4695cfc9d4cf69f63ed --- /dev/null +++ b/src/packages/animatingnumbers/demo.tsx @@ -0,0 +1,28 @@ +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 ( + <> +
+

CountUp-基础用法

+ +

CountUp-自定义样式,动态修改数据(需要指定最大位数)

+ +
+ + ) +} + +export default AnimatingNumbersDemo diff --git a/src/packages/animatingnumbers/doc.md b/src/packages/animatingnumbers/doc.md new file mode 100644 index 0000000000000000000000000000000000000000..770416cee1fd7560153a65dcd121caf2036c8c86 --- /dev/null +++ b/src/packages/animatingnumbers/doc.md @@ -0,0 +1,33 @@ +# 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 | diff --git a/src/packages/animatingnumbers/index.ts b/src/packages/animatingnumbers/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..98256bfaab9633c97e41128fa274fd4d092de9b4 --- /dev/null +++ b/src/packages/animatingnumbers/index.ts @@ -0,0 +1,4 @@ +import { AnimatingNumbers } from './animatingnumbers' +import { CountUp } from './countup' +AnimatingNumbers.CountUp = CountUp +export default AnimatingNumbers diff --git a/src/packages/nutui.react.ts b/src/packages/nutui.react.ts index 60898930bd2773d04f0b1f7b471376b4578d64a3..d7ba3a1965e480ac731bbdd7a1b6d09f5b0ce34b 100644 --- a/src/packages/nutui.react.ts +++ b/src/packages/nutui.react.ts @@ -27,6 +27,7 @@ import Uploader from './uploader' import Input from './input' import TextArea from './textarea' import CheckBox from './checkbox' +import AnimatingNumbers from './animatingnumbers' import Tag from './tag' import Badge from './badge' import Signature from './signature' @@ -61,6 +62,7 @@ export { Input, TextArea, CheckBox, + AnimatingNumbers, Tag, Badge, Signature, diff --git a/src/packages/signature/doc.md b/src/packages/signature/doc.md index 815ced88645b6dd0af63e168f209928fca05762e..1527cc5bbeb1a64d2ebe3440e56deb0bd3ec986b 100644 --- a/src/packages/signature/doc.md +++ b/src/packages/signature/doc.md @@ -23,7 +23,7 @@ const clear = () => { img.remove() } } -Signature confirm={confirm} clear={clear}> +

Tips: 点击确认按钮,下方显示签名图片