mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-08 04:18:23 +08:00
11c0a6a203
Where necessary, prefix the classes imported from react-component with 'Rc' rather than prefixing the Ant classes with 'Ant'. The prefixing of Ant classes wasn't consistent and isn't necessary in many cases.
133 lines
3.3 KiB
JavaScript
133 lines
3.3 KiB
JavaScript
import React, { createElement } from 'react';
|
|
import assign from 'object-assign';
|
|
import { isCssAnimationSupported } from 'css-animation';
|
|
|
|
function getNumberArray(num) {
|
|
return num ?
|
|
num.toString().split('').reverse().map(i => Number(i)) : [];
|
|
}
|
|
|
|
export default class ScrollNumber extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
animateStarted: true,
|
|
count: props.count
|
|
};
|
|
}
|
|
|
|
getPositionByNum(num, i) {
|
|
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) {
|
|
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,
|
|
}, () => {
|
|
this.props.onAnimated();
|
|
});
|
|
}, 5);
|
|
});
|
|
}
|
|
}
|
|
|
|
renderNumberList() {
|
|
const childrenToReturn = [];
|
|
for (let i = 0; i < 30; i++) {
|
|
childrenToReturn.push(<p key={i}>{i % 10}</p>);
|
|
}
|
|
return childrenToReturn;
|
|
}
|
|
|
|
renderCurrentNumber(num, i) {
|
|
const position = this.getPositionByNum(num, i);
|
|
const height = this.props.height;
|
|
const removeTransition = this.state.animateStarted ||
|
|
(getNumberArray(this.lastCount)[i] === undefined);
|
|
return createElement('span', {
|
|
className: `${this.props.prefixCls}-only`,
|
|
style: {
|
|
transition: removeTransition && 'none',
|
|
WebkitTransform: `translate3d(0, ${-position * height}px, 0)`,
|
|
transform: `translate3d(0, ${-position * height}px, 0)`,
|
|
height,
|
|
},
|
|
key: i,
|
|
}, this.renderNumberList());
|
|
}
|
|
|
|
renderNumberElement() {
|
|
const state = this.state;
|
|
if (!state.count || isNaN(state.count)) {
|
|
return state.count;
|
|
}
|
|
return getNumberArray(state.count)
|
|
.map((num, i) => this.renderCurrentNumber(num, i)).reverse();
|
|
}
|
|
|
|
render() {
|
|
const props = assign({}, this.props, {
|
|
className: `${this.props.prefixCls} ${this.props.className}`
|
|
});
|
|
const isBrowser = (typeof document !== 'undefined' && typeof window !== 'undefined');
|
|
if (isBrowser && isCssAnimationSupported) {
|
|
return createElement(
|
|
this.props.component,
|
|
props,
|
|
this.renderNumberElement()
|
|
);
|
|
}
|
|
return createElement(
|
|
this.props.component,
|
|
props,
|
|
props.count
|
|
);
|
|
}
|
|
}
|
|
|
|
ScrollNumber.defaultProps = {
|
|
prefixCls: 'ant-scroll-number',
|
|
count: null,
|
|
component: 'sup',
|
|
onAnimated() {},
|
|
height: 18,
|
|
};
|
|
|
|
ScrollNumber.propTypes = {
|
|
count: React.PropTypes.oneOfType([
|
|
React.PropTypes.string,
|
|
React.PropTypes.number
|
|
]),
|
|
component: React.PropTypes.string,
|
|
onAnimated: React.PropTypes.func,
|
|
height: React.PropTypes.number,
|
|
};
|