number.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * @fileOverview 自动计算数字坐标轴
  3. * @author dxq613@gmail.com
  4. */
  5. var isNil = require('@antv/util/lib/type/is-nil');
  6. var isNumber = require('@antv/util/lib/type/is-number');
  7. var AutoUtil = require('./util');
  8. var MIN_COUNT = 5;
  9. var MAX_COUNT = 7;
  10. var SNAP_COUNT_ARRAY = [0, 1, 1.2, 1.5, 1.6, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10];
  11. var SNAP_ARRAY = [0, 1, 2, 4, 5, 10];
  12. module.exports = function (info) {
  13. var min = info.min;
  14. var max = info.max;
  15. var interval = info.interval;
  16. var minTickInterval = info.minTickInterval;
  17. var ticks = [];
  18. var minCount = info.minCount || MIN_COUNT;
  19. var maxCount = info.maxCount || MAX_COUNT;
  20. var isFixedCount = minCount === maxCount; // 是否限定死了个数
  21. var minLimit = isNil(info.minLimit) ? -Infinity : info.minLimit; // 限定的最小值
  22. var maxLimit = isNil(info.maxLimit) ? Infinity : info.maxLimit; // 限定最大值
  23. var avgCount = (minCount + maxCount) / 2;
  24. var count = avgCount; // 用户传入的逼近数组
  25. var snapArray = info.snapArray ? info.snapArray : isFixedCount ? SNAP_COUNT_ARRAY : SNAP_ARRAY; // 如果限定大小范围,同时大小范围等于用户传入的范围,同时限定了个数,interval 按照个数均分
  26. if (min === minLimit && max === maxLimit && isFixedCount) {
  27. interval = (max - min) / (count - 1);
  28. }
  29. if (isNil(min)) {
  30. min = 0;
  31. }
  32. if (isNil(max)) {
  33. max = 0;
  34. }
  35. if (max === min) {
  36. if (min === 0) {
  37. max = 1;
  38. } else {
  39. if (min > 0) {
  40. min = 0;
  41. } else {
  42. max = 0;
  43. }
  44. }
  45. if (max - min < 5 && !interval && max - min >= 1) {
  46. interval = 1;
  47. }
  48. }
  49. if (isNil(interval)) {
  50. // 计算间距
  51. var temp = (max - min) / (avgCount - 1);
  52. interval = AutoUtil.snapFactorTo(temp, snapArray, 'ceil');
  53. if (maxCount !== minCount) {
  54. count = parseInt((max - min) / interval, 10);
  55. if (count > maxCount) {
  56. count = maxCount;
  57. }
  58. if (count < minCount) {
  59. count = minCount;
  60. } // 不确定tick的个数时,使得tick偏小
  61. interval = AutoUtil.snapFactorTo((max - min) / (count - 1), snapArray, 'floor');
  62. }
  63. } // interval should not be less than minTickInterval
  64. if (isNumber(minTickInterval) && interval < minTickInterval) {
  65. interval = minTickInterval;
  66. }
  67. if (info.interval || maxCount !== minCount) {
  68. // 校正 max 和 min
  69. max = Math.min(AutoUtil.snapMultiple(max, interval, 'ceil'), maxLimit); // 向上逼近
  70. min = Math.max(AutoUtil.snapMultiple(min, interval, 'floor'), minLimit); // 向下逼近
  71. count = Math.round((max - min) / interval);
  72. min = AutoUtil.fixedBase(min, interval);
  73. max = AutoUtil.fixedBase(max, interval);
  74. } else {
  75. avgCount = parseInt(avgCount, 10); // 取整
  76. var avg = (max + min) / 2;
  77. var avgTick = AutoUtil.snapMultiple(avg, interval, 'ceil');
  78. var sideCount = Math.floor((avgCount - 2) / 2);
  79. var maxTick = avgTick + sideCount * interval;
  80. var minTick;
  81. if (avgCount % 2 === 0) {
  82. minTick = avgTick - sideCount * interval;
  83. } else {
  84. minTick = avgTick - (sideCount + 1) * interval;
  85. }
  86. if (maxTick < max) {
  87. maxTick = maxTick + interval;
  88. }
  89. if (minTick > min) {
  90. minTick = minTick - interval;
  91. }
  92. max = AutoUtil.fixedBase(maxTick, interval);
  93. min = AutoUtil.fixedBase(minTick, interval);
  94. }
  95. max = Math.min(max, maxLimit);
  96. min = Math.max(min, minLimit);
  97. ticks.push(min);
  98. for (var i = 1; i < count; i++) {
  99. var tickValue = AutoUtil.fixedBase(interval * i + min, interval);
  100. if (tickValue < max) {
  101. ticks.push(tickValue);
  102. }
  103. }
  104. if (ticks[ticks.length - 1] < max) {
  105. ticks.push(max);
  106. }
  107. return {
  108. min: min,
  109. max: max,
  110. interval: interval,
  111. count: count,
  112. ticks: ticks
  113. };
  114. };