提交 9d4aa291 编写于 作者: A afc163

Refactor ant scroll number

上级 3768e495
import React, { createElement } from 'react';
import { findDOMNode } from 'react-dom';
import { getPartNumber, getTranslateY } from './utils';
import assign from 'object-assign';
import { Children } from 'rc-util';
class AntNumber extends React.Component {
constructor(props) {
super(props);
const children = Children.toArray(this.props.children);
this.endSetState = false;
this.count = this.props.count;
this.data = getPartNumber(this.count);
this.timeout = null;
this.state = {
children,
};
}
getNumberOnly(index, style) {
const childrenToReturn = [];
for (let i = 0; i < 30; i++) {
let count = i >= 10 ? i % 10 : i;
childrenToReturn.push(<p key={i}>{count}</p>);
}
return createElement('span', {
className: `${this.props.prefixCls}-only`,
style: style,
key: index,
}, childrenToReturn);
}
setEndState(style) {
this.endSetState = true;
style.transition = 'none';
}
getNumberElement(props) {
const count = props.count;
if (!count || count === '') {
return null;
}
const length = count.toString().length;
const data = getPartNumber(count);
const height = findDOMNode(this).offsetHeight;
const differ = count - this.count;
let childrenWap = [];
let i = 0;
while (i < length) {
const style = {};
const Y = getTranslateY(differ, data, this.data, i) || -(data[i] + 10);
const translateY = Y * height;
if (count !== this.count) {
this.setEndState(style);
}
style.transform = `translateY(${translateY}px)`;
const children = this.getNumberOnly(i, style);
childrenWap.unshift(children);
i++;
}
this.data = data;
this.count = count;
return childrenWap;
}
updateChildren(props) {
if (typeof props.count === 'string') {
this.data = getPartNumber(this.props.max);
this.count = this.props.max;
return this.setState({
children: [props.count],
});
}
const newChildren = this.getNumberElement(props);
if (newChildren && newChildren.length) {
this.setState({
children: newChildren,
}, () => {
if (this.endSetState) {
this.updateChildren(props);
this.endSetState = false;
}
});
}
}
animEnd() {
clearTimeout(this.timeout);
this.timeout = setTimeout(this.props.callback, 300);
}
componentDidMount() {
this.updateChildren(this.props);
}
componentWillReceiveProps(nextProps) {
this.updateChildren(nextProps);
this.animEnd();
}
render() {
const props = assign({}, this.props, {
className: `${this.props.prefixCls} ${this.props.className}`
});
return createElement(
this.props.component,
props,
this.state.children
);
}
}
AntNumber.defaultProps = {
prefixCls: 'ant-number',
count: null,
max: null,
component: 'sup',
callback: function() {},
};
AntNumber.propTypes = {
count: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
]),
component: React.PropTypes.string,
callback: React.PropTypes.func,
max: React.PropTypes.number,
};
export default AntNumber;
import React, { createElement } from 'react';
import assign from 'object-assign';
function getNumberArray(num) {
return num ?
num.toString().split('').map(i => Number(i)) : [];
}
class AntScrollNumber extends React.Component {
constructor(props) {
super(props);
this.state = {
animated: true
};
}
getPositionByNum(num, i) {
if (this.state.animated) {
return 10 + num;
}
const currentDigit = getNumberArray(this.props.count)[i];
const lastDigit = getNumberArray(this.lastCount)[i];
// 同方向则在同一侧切换数字
if (this.props.count > this.lastCount) {
if (currentDigit >= lastDigit) {
return 10 + num;
} else {
return 20 + num;
}
} else {
if (currentDigit <= lastDigit) {
return 10 + num;
} else {
return num;
}
}
}
componentWillReceiveProps(nextProps) {
if ('count' in nextProps && nextProps.count) {
if (this.lastCount !== this.props.count) {
this.lastCount = this.props.count;
this.setState({
animated: false
}, () => {
setTimeout(() => {
this.setState({
animated: true
});
this.props.callback();
}, 300);
});
}
}
}
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;
return createElement('span', {
className: `${this.props.prefixCls}-only`,
style: {
transition: this.state.animated && 'none',
transform: 'translate3d(0, ' + (-position * height) + 'px, 0)',
height: height,
},
key: i,
}, this.renderNumberList());
}
renderNumberElement() {
const props = this.props;
if (!props.count || isNaN(props.count)) {
return props.count;
}
return getNumberArray(props.count)
.map((num, i) => this.renderCurrentNumber(num, i));
}
render() {
const props = assign({}, this.props, {
className: `${this.props.prefixCls} ${this.props.className}`
});
return createElement(
this.props.component,
props,
this.renderNumberElement()
);
}
}
AntScrollNumber.defaultProps = {
prefixCls: 'ant-scroll-number',
count: null,
component: 'sup',
callback: function() {},
height: 20
};
AntScrollNumber.propTypes = {
count: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
]),
component: React.PropTypes.string,
callback: React.PropTypes.func,
height: React.PropTypes.number,
};
export default AntScrollNumber;
import React from 'react';
import Animate from 'rc-animate';
import AntNumber from './AntNumber';
import ScrollNumber from './ScrollNumber';
class AntBadge extends React.Component {
constructor(props) {
......@@ -31,7 +31,7 @@ class AntBadge extends React.Component {
transitionAppear={true}>
{
hidden ? null :
<AntNumber data-show={!hidden} className={className} count={count} max={99}/>
<ScrollNumber data-show={!hidden} className={className} count={count} />
}
</Animate>
</span>
......
export function getPartNumber(num) {
return num ?
num.toString().split('').map(i => Number(i)).reverse() : [];
}
export function getTranslateY(differ, data, _data, i) {
let translateY = 0;
if (!differ) {
//不想插入40个,改变要滚到的距离;
if (_data[i + '_add']) {
return -(data[i] + 20);
}
if (_data[i + '_rem']) {
return -data[i];
}
return false;
}
//判断相差的位数来驱动数字;差个位滚动一格,差10的部分及以上个位滚动一周;
/*
* 区域段
* 0-9:0
* 0-9:1
* 0-9:2
* */
const countToString = Math.abs(differ).toString();
const countLength = countToString.length;
const on = _data[i];
const to = data[i];
if (differ > 0) {
if (countLength - 1 > i) {
//差值位数大于1时,参数的位置,到达减去两个参数的差,在0区域段;
translateY = -(to - (to - on));
//on大于to且differ大于10,如9->0,需要设计滚动到的位置+10;
if (on > to) {
data[i + '_add'] = true;
}
} else if (countLength - 1 < i && to === on) {
//参数不变动;
translateY = null;
} else if (typeof on === 'undefined') {
//新增加入时设为0;
translateY = -10;
} else {
//如果开始大于到达,到达(to)加10;
const _to = on > to ? to + 10 : to;
//差值为一位数时,到达减去两个参数的差,在1区域段,加10;
translateY = -(to - (_to - on) + 10);
}
} else {
if (countLength - 1 > i) {
//差值位数大于1时,参数的位置,到达加上两个参数的差,在2区域段,加20,需要滚动一周;
translateY = -(to + (on - to) + 20);
//同上,differ大于10时,且to在于on
if (to > on) {
data[i + '_rem'] = true;
}
} else if (countLength - 1 < i && to === on) {
translateY = null;
} else {
//如果到达大于开始,开始(on)加10;
const _on = on < to ? on + 10 : on;
//差值位数小于1时,参数的位置,到达减去两个参数的差,在1区域段,加10,往上滚回差值;
translateY = -(to + (_on - to) + 10);
}
}
return translateY;
}
@badge-prefix-cls: ~"@{css-prefix}badge";
@number-prefix-cls: ~"@{css-prefix}number";
@number-prefix-cls: ~"@{css-prefix}scroll-number";
.@{badge-prefix-cls} {
position: relative;
......@@ -67,7 +67,7 @@ a .@{badge-prefix-cls} {
overflow: hidden;
&-only{
display: inline-block;
transition: transform .3s @ease-in-out;
transition: transform .3s @ease-in-out;//transform .3s @ease-in-out;
}
}
......@@ -90,3 +90,4 @@ a .@{badge-prefix-cls} {
transform: scale(0) translateX(-50%);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册