仓库
yaxis-transformer已经发布到npm, , 欢迎star。
前言
前不久笔者分享过的基本思路,当时需求比较紧张,苦于没有时间去整理代码。现在刚好空闲下来,回头看看之前的代码,发现存在几个问题:业务侵入性太强, 定制化能力太弱和方案设计不够合理。所以决定这一次趁热打铁,对整个方案重新设计,将y轴的数据变换能力抽成底层功能库,并且提供足够强的定制化能力。这样的好处是可以移出之前的业务逻辑代码,避免库逻辑混乱和过于累赘,将业务逻辑的处理转交给使用者。
分析
整个方案大致可以分四个步骤:
- 处理最小值minData,找出规整间距interval,计算最大值maxData;
- 找出需要格式化的单位unit;
- 计算建议小数位数adviseDecimal;
- 生成最终结果transformResult。
1. 数据处理
以下例子使用的count=3,即总共生成四个数据。
-
首先是处理最小值minData, 首先根据原始的interval得到规整的基准值baseInterval, baseInterval的作用是找出minData需要处理的部分remainPart,例如minData为1542,baseInterval为200,那么可知remainPart为542,接着再对remainPart进行查找基准值的操作,假定结果为500,那么处理之后的minData就为1000 + 500 = 1500。
-
找出规整间距interval,根据前面处理的minData和原始的maxData,再根据基准值生成的策略得到新的间距,如minData=1000, maxData=6100, interval=1700, 生成的基准值数组为1000, 2000, 5000, 生成的策略如下:
defaultBaseGenStrategy = (originInterval: number) => { let base = AxisHelper.genPowNum(originInterval) return [10 * base, 5 * base, 2 * base, base] }复制代码
那对于间距来说,需要取出第一个比它大的数,所以可算出interval就是2000。
- 最大值就等于 minData + count * interval
2. 找出格式化单位
通常会预设一组用于格式化的单位,例如:[{range: 10000, unit: "万"}, {range: 100000000, unit: "亿"}]
{range:0.01, unit:"%"}
对于单位的格式化,主要在于使用哪个值用来做单位的查找,因此我提供了maxData和minData两种选择。 3. 计算建议小数位数
所以建议的小数位数,我这里的定义是指在单位unit的格式化下,仍然能完整显示出所有有效的小数位数。例如一组数据[100, 10100, 20100],单位是{range: 10000, unit: "万"}
, 那么建议的小数位数就是2,这样格式化出来的数据就是[0.01万, 1.01万,2.01万]。
4. 生成结果
当完成上述步骤,结果就已经呼之欲出。最后就是生成相应的数组,格式大致如下:
{ data: [0, 10000, 20000, 30000], dataUnit: ['0.00', '1.00万', '2.00万', '3.00万'], adviseDecimal: 1 }复制代码
使用
const yaxisTransformer = new YaxisTransformer([1542, 6100]) let transformResult = yaxisTransformer .withCount(3) .withMinToZero(false) .withUnitFollowMax(false) .withFormatRuler((data, decimal) => { return data.toFixed(decimal) }) .withUnitSet([{range:10000, unit:"万"}]) .transform()复制代码
通过建造者模式,增加灵活的定制化配置,目前有的配置如下:
withCount
设置生成间距的数量,四个数的数组count即为3withUnitSet
设置格式化单位,默认为[{range: 10000, unit: "万"}, {range: 100000000, unit: "亿"}]
withPercentUnit
使用百分比做格式化withMinMaxData
设置最大值最小值withBaseGenStrategy
设置基准值生成策略,默认为
defaultBaseGenStrategy = (originInterval: number) => { let base = AxisHelper.genPowNum(originInterval) return [10 * base, 5 * base, 2 * base, base] }复制代码
-
withFormatRuler
设置格式化小数位数的规则,默认为number.toFixed(decimal)
-
withForceDecimal
强制设置小数位数 -
withKeepZeroUnit
是否保留0的单位 -
withKeepUnitSame
数组里的每个值单位是否保持单位一致 -
withUnitFollowMax
格式化的单位否是参考最大值 -
withMinToZero
最小值< 间距时,是否取0, 如min=100,interval为1000,是否令min = 0 -
withKeepZeroDecimal
是否保持0的小数位数,如0.00是否格式化为0
提供了大量能想到用以配置的属性。
总结
对于底层通用库,亟需遵守开闭原则,对扩展开放,对修改封闭,对于npm的库,天然就是封闭的,所以开放就需要提供足够的定制化能力,减少自己业务逻辑的侵入。