NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/scale/lib/auto/number.js
2023-09-14 14:47:11 +08:00

165 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @fileOverview 自动计算数字坐标轴
* @author dxq613@gmail.com
*/
var isNil = require('@antv/util/lib/type/is-nil');
var isNumber = require('@antv/util/lib/type/is-number');
var AutoUtil = require('./util');
var MIN_COUNT = 5;
var MAX_COUNT = 7;
var SNAP_COUNT_ARRAY = [1, 1.2, 1.5, 1.6, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10];
var SNAP_ARRAY = [1, 2, 4, 5, 10];
var EPS = 1e-12;
module.exports = function (info) {
var min = info.min;
var max = info.max;
var interval = info.interval;
var minTickInterval = info.minTickInterval;
var ticks = [];
var minCount = info.minCount || MIN_COUNT;
var maxCount = info.maxCount || MAX_COUNT;
var isFixedCount = minCount === maxCount; // 是否限定死了个数
var minLimit = isNil(info.minLimit) ? -Infinity : info.minLimit; // 限定的最小值
var maxLimit = isNil(info.maxLimit) ? Infinity : info.maxLimit; // 限定最大值
var avgCount = (minCount + maxCount) / 2;
var count = avgCount; // 用户传入的逼近数组
var snapArray = info.snapArray ? info.snapArray : isFixedCount ? SNAP_COUNT_ARRAY : SNAP_ARRAY; // 如果限定大小范围同时大小范围等于用户传入的范围同时限定了个数interval 按照个数均分
if (min === minLimit && max === maxLimit && isFixedCount) {
interval = (max - min) / (count - 1);
}
if (isNil(min)) {
min = 0;
}
if (isNil(max)) {
max = 0;
}
if (Math.abs(max - min) < EPS) {
if (min === 0) {
max = 1;
} else {
if (min > 0) {
min = 0;
} else {
max = 0;
}
}
if (max - min < 5 && !interval && max - min >= 1) {
interval = 1;
}
}
if (isNil(interval)) {
// 计算间距
var temp = (max - min) / (avgCount - 1);
interval = AutoUtil.snapFactorTo(temp, snapArray, 'ceil');
if (maxCount !== minCount) {
count = parseInt((max - min) / interval, 10);
if (count > maxCount) {
count = maxCount;
}
if (count < minCount) {
count = minCount;
} // 不确定tick的个数时使得tick偏小
interval = AutoUtil.snapFactorTo((max - min) / (count - 1), snapArray);
}
} // interval should not be less than minTickInterval
if (isNumber(minTickInterval) && interval < minTickInterval) {
interval = minTickInterval;
}
if (info.interval || maxCount !== minCount) {
// 校正 max 和 min
max = Math.min(AutoUtil.snapMultiple(max, interval, 'ceil'), maxLimit); // 向上逼近
min = Math.max(AutoUtil.snapMultiple(min, interval, 'floor'), minLimit); // 向下逼近
count = Math.round((max - min) / interval);
min = AutoUtil.fixedBase(min, interval); // 当min为负数的时候fixedBase后min可能会大于minLimit导致最终产出的tick是大于minLimit的所以必须进行修正
max = AutoUtil.fixedBase(max, interval);
var prevMin = null;
while (min > minLimit && minLimit > -Infinity && (prevMin === null || min < prevMin)) {
// 保证计算出来的刻度最小值 min 不大于数据最小值 min
prevMin = min;
min = AutoUtil.fixedBase(min - interval, interval);
}
} else {
avgCount = parseInt(avgCount, 10); // 取整
var avg = (max + min) / 2;
var avgTick = AutoUtil.snapMultiple(avg, interval, 'ceil');
var sideCount = Math.floor((avgCount - 2) / 2);
var maxTick = avgTick + sideCount * interval;
var minTick;
if (avgCount % 2 === 0) {
minTick = avgTick - sideCount * interval;
} else {
minTick = avgTick - (sideCount + 1) * interval;
}
var prevMaxTick = null; // 如果减去intervl, fixBase后新的minTick没有大于之前的值就退出防止死循环
while (maxTick < max && (prevMaxTick === null || maxTick > prevMaxTick)) {
// 保证计算出来的刻度最大值 maxTick 不小于数据最大值 max
prevMaxTick = maxTick;
maxTick = AutoUtil.fixedBase(maxTick + interval, interval);
}
var prevMinTick = null; // 如果减去intervl, fixBase后新的minTick没有小于之前的值就退出防止死循环
while (minTick > min && (prevMinTick === null || minTick < prevMinTick)) {
// 保证计算出来的刻度最小值 minTick 不大于数据最小值 min
prevMinTick = minTick;
minTick = AutoUtil.fixedBase(minTick - interval, interval); // 防止超常浮点数计算问题
}
max = maxTick;
min = minTick;
}
max = Math.min(max, maxLimit);
min = Math.max(min, minLimit);
ticks.push(min);
for (var i = 1; i < count; i++) {
var tickValue = AutoUtil.fixedBase(interval * i + min, interval);
if (tickValue < max) {
ticks.push(tickValue);
}
}
if (ticks[ticks.length - 1] < max) {
ticks.push(max);
}
return {
min: min,
max: max,
interval: interval,
count: count,
ticks: ticks
};
};