需求: TweenOne显示数字组件当数据太大的时候显示数据不对,需要显示正确数据。
解决过程:
找到以下相关issue:
https://github.com/ant-design/ant-motion/issues/210
https://github.com/ant-design/ant-motion/issues/234
更新到最新版本后问题仍然存在,然后去查看了源代码看到插件内部没有使用bignumber进行处理,数据大的时候还是会有问题,因此决定使用bignumber对这个插件进行改动使其支持bignumber,进而满足业务需求。
原因:
使用的插件
import Children from 'rc-tween-one/lib/plugin/ChildrenPlugin';
没有使用bignumber进行处理。
解决方案:
修改这个插件使其满足需要,修改前的代码如下:
https://github.com/react-component/tween-one/blob/master/src/plugin/ChildrenPlugin.jsx
修改后的核心代码如下:
ChildrenPlugin.prototype = {
setRatio(ratio) {
const { valueStr, floatLength, formatMoney } = this.vars;
let v ;
// = (value - this.start.value) * ratio + this.start.value;
v = new BigNumber(valueStr).minus(this.start.value).multipliedBy(ratio).plus(this.start.value);
if (typeof floatLength === 'number') {
if (floatLength) {
v = YData.removeTail0(v.toFixed(floatLength));//删除尾部无效的0
} else {
v = v.toFixed(0);
}
}
v = formatMoney ? this.toMoney(v, formatMoney) : v;
this.target.innerHTML = v;
},
};
添加了字段:valueStr将字符串传到AnimateNumber
import React from 'react';
import TweenOne from 'rc-tween-one';
// import Children from 'rc-tween-one/lib/plugin/ChildrenPlugin';
import config from 'utils/config';
import YData from 'appRoot/utils/YData';
import BigNumber from 'bignumber.js';
const ChildrenPlugin = function (target, vars) {
this.target = target;
this.vars = vars;
};
ChildrenPlugin.prototype = {
name: 'Children',
getAnimStart() {
const { formatMoney } = this.vars;
const opts = {
thousand: formatMoney && formatMoney.thousand || ',',
decimal: formatMoney && formatMoney.decimal || '.',
};
const rep = new RegExp(`\\${opts.thousand}`, 'g');
this.start = this.vars.startAt || {
value: parseFloat(this.target.innerHTML.replace(rep, '').replace(opts.decimal, '.')) || 0
};
},
toMoney(v, _opts) {
const opts = {
thousand: _opts.thousand || ',',
decimal: _opts.decimal || '.',
};
const negative = parseFloat(v) < 0 ? '-' : '';
const numberArray = v.toString().split('.');
const base = Math.abs(parseInt(numberArray[0], 10)).toString();
const mod = base.length > 3 ? base.length % 3 : 0;
const decimal = numberArray[1];
return `${negative}${mod ? `${base.substr(0, mod)}${opts.thousand}` : ''}${
base.substr(mod).replace(/(\d{3})(?=\d)/g, `$1${opts.thousand}`)}${
decimal ? `${opts.decimal}${decimal}` : ''
}`;
},
setRatio(ratio) {
const { valueStr, floatLength, formatMoney } = this.vars;
let v ;
// = (value - this.start.value) * ratio + this.start.value;
v = new BigNumber(valueStr).minus(this.start.value).multipliedBy(ratio).plus(this.start.value);
const vString = v.toString();
console.log('vString',vString)
if (typeof floatLength === 'number') {
if (floatLength) {
v = YData.removeTail0(v.toFixed(floatLength));//删除尾部无效的0
} else {
v = v.toFixed(0);
}
}
v = formatMoney ? this.toMoney(v, formatMoney) : v;
this.target.innerHTML = v;
},
};
const Children = ChildrenPlugin;
TweenOne.plugins.push(Children);
/**
* 使 TweenOne 支持bignumber显示,添加了plugin Children 字段 valueStr
* <AnimateNumber
valueStr={valueStr} //valueStr = '1234567890123456789.1234567899';
value={Number(valueStr)}
floatLength={2}
/>
*
* @param {*} props
*/
const AnimateNumber = (props) => {
const { value, valueStr, formatMoney = true, floatLength = config.MAX_DECIMAL_DIGITS, duration = 1000, style } = props;
const animation = value || value === 0 ? {
Children: {
value: Number(valueStr),
valueStr: `${valueStr}`,
floatLength,
formatMoney,
},
duration,
} : null;
return (
<TweenOne
animation={animation}
style={style}
>
0
</TweenOne>
);
};
export default AnimateNumber;
参考:
https://motion.ant.design/components/tween-one#components-tween-one-demo-easingPath
网友评论