linear-tick.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // 认为是nice的刻度
  2. var SNAP_COUNT_ARRAY = [1, 1.2, 1.5, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10];
  3. var DEFAULT_COUNT = 5; // 默认刻度值
  4. export default (function (cfg) {
  5. var {
  6. tickCount,
  7. tickInterval
  8. } = cfg || {};
  9. var {
  10. min,
  11. max
  12. } = cfg || {};
  13. min = isNaN(min) ? 0 : min;
  14. max = isNaN(max) ? 0 : max;
  15. var count = tickCount && tickCount >= 2 ? tickCount : DEFAULT_COUNT; // 计算interval, 优先取tickInterval
  16. var interval = tickInterval || getBestInterval({
  17. tickCount: count,
  18. max,
  19. min
  20. }); // 通过interval计算最小tick
  21. var minTick = Math.floor(min / interval) * interval; // 如果指定了tickInterval, count 需要根据指定的tickInterval来算计
  22. if (tickInterval) {
  23. var intervalCount = Math.abs(Math.ceil((max - minTick) / tickInterval)) + 1; // tickCount 作为最小 count 处理
  24. count = Math.max(count, intervalCount);
  25. }
  26. var ticks = [];
  27. var tickLength = 0;
  28. var fixedLength = getFixedLength(interval);
  29. while (tickLength < count) {
  30. ticks.push(toFixed(minTick + tickLength * interval, fixedLength));
  31. tickLength++;
  32. }
  33. return ticks;
  34. });
  35. var DECIMAL_LENGTH = 12;
  36. function getFactor(number) {
  37. // 取正数
  38. number = Math.abs(number);
  39. var factor = 1;
  40. if (number === 0) {
  41. return factor;
  42. } // 小于1,逐渐放大
  43. if (number < 1) {
  44. var count = 0;
  45. while (number < 1) {
  46. factor = factor / 10;
  47. number = number * 10;
  48. count++;
  49. } // 浮点数计算出现问题
  50. if (factor.toString().length > DECIMAL_LENGTH) {
  51. factor = parseFloat(factor.toFixed(count));
  52. }
  53. return factor;
  54. } // 大于10逐渐缩小
  55. while (number > 10) {
  56. factor = factor * 10;
  57. number = number / 10;
  58. }
  59. return factor;
  60. } // 获取最佳匹配刻度
  61. function getBestInterval(_ref) {
  62. var {
  63. tickCount,
  64. min,
  65. max
  66. } = _ref;
  67. // 如果最大最小相等,则直接按1处理
  68. if (min === max) {
  69. return 1 * getFactor(max);
  70. } // 1.计算平均刻度间隔
  71. var avgInterval = (max - min) / (tickCount - 1); // 2.数据标准归一化 映射到[1-10]区间
  72. var factor = getFactor(avgInterval);
  73. var calInterval = avgInterval / factor;
  74. var calMax = max / factor;
  75. var calMin = min / factor; // 根据平均值推算最逼近刻度值
  76. var similarityIndex = 0;
  77. for (var index = 0; index < SNAP_COUNT_ARRAY.length; index++) {
  78. var item = SNAP_COUNT_ARRAY[index];
  79. if (calInterval <= item) {
  80. similarityIndex = index;
  81. break;
  82. }
  83. }
  84. var similarityInterval = getInterval(similarityIndex, tickCount, calMin, calMax); // 小数点位数还原到数据的位数, 因为similarityIndex有可能是小数,所以需要保留similarityIndex自己的小数位数
  85. var fixedLength = getFixedLength(similarityInterval) + getFixedLength(factor);
  86. return toFixed(similarityInterval * factor, fixedLength);
  87. }
  88. function getInterval(startIndex, tickCount, min, max) {
  89. var verify = false;
  90. var interval = SNAP_COUNT_ARRAY[startIndex]; // 刻度值校验,如果不满足,循环下去
  91. for (var i = startIndex; i < SNAP_COUNT_ARRAY.length; i++) {
  92. if (intervalIsVerify({
  93. interval: SNAP_COUNT_ARRAY[i],
  94. tickCount,
  95. max,
  96. min
  97. })) {
  98. // 有符合条件的interval
  99. interval = SNAP_COUNT_ARRAY[i];
  100. verify = true;
  101. break;
  102. }
  103. } // 如果不满足, 依次缩小10倍,再计算
  104. if (!verify) {
  105. return 10 * getInterval(0, tickCount, min / 10, max / 10);
  106. }
  107. return interval;
  108. } // 刻度是否满足展示需求
  109. function intervalIsVerify(_ref2) {
  110. var {
  111. interval,
  112. tickCount,
  113. max,
  114. min
  115. } = _ref2;
  116. var minTick = Math.floor(min / interval) * interval;
  117. if (minTick + (tickCount - 1) * interval >= max) {
  118. return true;
  119. }
  120. return false;
  121. } // 计算小数点应该保留的位数
  122. function getFixedLength(num) {
  123. var str = num.toString();
  124. var index = str.indexOf('.');
  125. var indexOfExp = str.indexOf('e-');
  126. var length = indexOfExp >= 0 ? parseInt(str.substr(indexOfExp + 2), 10) : str.substr(index + 1).length;
  127. if (length > 20) {
  128. // 最多保留20位小数
  129. length = 20;
  130. }
  131. return length;
  132. } // @antv/util fixedbase不支持科学计数法的判断,需要提mr
  133. function toFixed(v, length) {
  134. return parseFloat(v.toFixed(length));
  135. }