You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
4.4 KiB

import * as React from 'react';
8 years ago
import { createElement, Component } from 'react';
import omit from 'omit.js';
import classNames from 'classnames';
function getNumberArray(num: string | number | undefined | null) {
return num ?
num.toString()
.split('')
.reverse()
.map(i => Number(i)) : [];
}
export interface ScrollNumberProps {
prefixCls?: string;
className?: string;
count?: string | number | null;
displayComponent?: React.ReactElement<any>;
component?: string;
onAnimated?: Function;
style?: React.CSSProperties;
title?: string | number | null;
}
export interface ScrollNumberState {
animateStarted?: boolean;
count?: string | number | null;
}
export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNumberState> {
static defaultProps = {
prefixCls: 'ant-scroll-number',
count: null,
onAnimated() {
},
};
8 years ago
lastCount: any;
constructor(props: ScrollNumberProps) {
super(props);
this.state = {
animateStarted: true,
count: props.count,
};
}
getPositionByNum(num: number, i: number) {
if (this.state.animateStarted) {
return 10 + num;
}
const currentDigit = getNumberArray(this.state.count)[i];
const lastDigit = getNumberArray(this.lastCount)[i];
// 同方向则在同一侧切换数字
if (this.state.count! > this.lastCount) {
if (currentDigit >= lastDigit) {
return 10 + num;
}
return 20 + num;
}
if (currentDigit <= lastDigit) {
return 10 + num;
}
return num;
}
componentWillReceiveProps(nextProps: ScrollNumberProps) {
if ('count' in nextProps) {
if (this.state.count === nextProps.count) {
return;
}
this.lastCount = this.state.count;
// 复原数字初始位置
this.setState({
animateStarted: true,
}, () => {
// 等待数字位置复原完毕
// 开始设置完整的数字
setTimeout(() => {
this.setState({
animateStarted: false,
count: nextProps.count,
}, () => {
const onAnimated = this.props.onAnimated;
if (onAnimated) {
onAnimated();
}
});
}, 5);
});
}
}
renderNumberList(position: number) {
const childrenToReturn: React.ReactElement<any>[] = [];
for (let i = 0; i < 30; i++) {
const currentClassName = (position === i) ? 'current' : '';
childrenToReturn.push(<p key={i.toString()} className={currentClassName}>{i % 10}</p>);
}
return childrenToReturn;
}
renderCurrentNumber(num: number, i: number) {
const position = this.getPositionByNum(num, i);
const removeTransition = this.state.animateStarted ||
(getNumberArray(this.lastCount)[i] === undefined);
return createElement('span', {
className: `${this.props.prefixCls}-only`,
style: {
transition: removeTransition ? 'none' : undefined,
msTransform: `translateY(${-position * 100}%)`,
WebkitTransform: `translateY(${-position *