@progress/kendo-charts
Version:
Kendo UI platform-independent Charts library
370 lines (297 loc) • 11.7 kB
JavaScript
import Axis from './axis';
import AxisLabel from './axis-label';
import Box from './box';
import { BLACK, DEFAULT_PRECISION, COORD_PRECISION } from '../common/constants';
import { deepExtend, defined, limitValue, round, setDefaultOptions, valueOrDefault } from '../common';
import autoMajorUnit from './utils/auto-major-unit';
import autoAxisMin from './utils/auto-axis-min';
import autoAxisMax from './utils/auto-axis-max';
import floor from './utils/floor';
import ceil from './utils/ceil';
import limitCoordinate from './utils/limit-coordinate';
var MIN_VALUE_RANGE = Math.pow(10, -DEFAULT_PRECISION + 1);
var NumericAxis = (function (Axis) {
function NumericAxis(seriesMin, seriesMax, options, chartService) {
Axis.call(this, Object.assign({}, options, {
seriesMin: seriesMin,
seriesMax: seriesMax
}), chartService);
}
if ( Axis ) NumericAxis.__proto__ = Axis;
NumericAxis.prototype = Object.create( Axis && Axis.prototype );
NumericAxis.prototype.constructor = NumericAxis;
NumericAxis.prototype.initUserOptions = function initUserOptions (options) {
var autoOptions = autoAxisOptions(options.seriesMin, options.seriesMax, options);
this.totalOptions = totalAxisOptions(autoOptions, options);
return axisOptions(autoOptions, options);
};
NumericAxis.prototype.initFields = function initFields () {
this.totalMin = this.totalOptions.min;
this.totalMax = this.totalOptions.max;
this.totalMajorUnit = this.totalOptions.majorUnit;
this.seriesMin = this.options.seriesMin;
this.seriesMax = this.options.seriesMax;
};
NumericAxis.prototype.clone = function clone () {
return new NumericAxis(
this.seriesMin,
this.seriesMax,
Object.assign({}, this.options),
this.chartService
);
};
NumericAxis.prototype.startValue = function startValue () {
return 0;
};
NumericAxis.prototype.range = function range () {
var options = this.options;
return { min: options.min, max: options.max };
};
NumericAxis.prototype.getDivisions = function getDivisions (stepValue) {
if (stepValue === 0) {
return 1;
}
var options = this.options;
var range = options.max - options.min;
return Math.floor(round(range / stepValue, COORD_PRECISION)) + 1;
};
NumericAxis.prototype.getTickPositions = function getTickPositions (unit, skipUnit) {
var options = this.options;
var ref = this.lineInfo();
var axisDir = ref.axisDir;
var axisOrigin = ref.axisOrigin;
var lineBox = ref.lineBox;
var lineSize = ref.lineSize;
var range = options.max - options.min;
var scale = lineSize / range;
var step = unit * scale;
var divisions = this.getDivisions(unit);
var positions = [];
var pos = lineBox[axisOrigin];
var skipStep = 0;
if (skipUnit) {
skipStep = skipUnit / unit;
}
for (var idx = 0; idx < divisions; idx++) {
if (idx % skipStep !== 0) {
positions.push(round(pos, COORD_PRECISION));
}
pos = pos + step * axisDir;
}
return positions;
};
NumericAxis.prototype.getMajorTickPositions = function getMajorTickPositions () {
return this.getTickPositions(this.options.majorUnit);
};
NumericAxis.prototype.getMinorTickPositions = function getMinorTickPositions () {
return this.getTickPositions(this.options.minorUnit);
};
NumericAxis.prototype.getSlot = function getSlot (a, b, limit) {
if ( limit === void 0 ) limit = false;
var options = this.options;
var ref = this.lineInfo();
var axis = ref.axis;
var axisDir = ref.axisDir;
var lineBox = ref.lineBox;
var lineSize = ref.lineSize;
var lineStart = ref.lineStart;
var step = axisDir * (lineSize / (options.max - options.min));
var start = valueOrDefault(a, b || 0);
var end = valueOrDefault(b, a || 0);
if (limit) {
start = limitValue(start, options.min, options.max);
end = limitValue(end, options.min, options.max);
}
var p1 = Math.min(start, end) - options.min;
var p2 = Math.max(start, end) - options.min;
var slotBox = new Box(lineBox.x1, lineBox.y1, lineBox.x1, lineBox.y1);
slotBox[axis + 1] = limitCoordinate(lineStart + step * (axisDir > 0 ? p1 : p2));
slotBox[axis + 2] = limitCoordinate(lineStart + step * (axisDir > 0 ? p2 : p1));
return slotBox;
};
NumericAxis.prototype.getValue = function getValue (point) {
var options = this.options;
var max = Number(options.max);
var min = Number(options.min);
var offset = this.pointOffset(point);
var valueOffset = offset * (max - min);
if (offset < 0 || offset > 1) {
return null;
}
var value = min + valueOffset;
return round(value, DEFAULT_PRECISION);
};
NumericAxis.prototype.translateRange = function translateRange (delta) {
var options = this.options;
var vertical = options.vertical;
var reverse = options.reverse;
var max = options.max;
var min = options.min;
var ref = this.lineInfo();
var lineSize = ref.lineSize;
var range = max - min;
var scale = lineSize / range;
var offset = round(delta / scale, DEFAULT_PRECISION);
if ((vertical || reverse) && !(vertical && reverse )) {
offset = -offset;
}
return {
min: min + offset,
max: max + offset,
offset: offset
};
};
NumericAxis.prototype.labelsCount = function labelsCount () {
return this.getDivisions(this.options.majorUnit);
};
NumericAxis.prototype.createAxisLabel = function createAxisLabel (index, labelOptions, labelContext) {
var options = this.options;
var value = round(options.min + (index * options.majorUnit), DEFAULT_PRECISION);
var text = this.axisLabelText(value, labelOptions, labelContext);
return new AxisLabel(value, text, index, null, labelOptions);
};
NumericAxis.prototype.shouldRenderNote = function shouldRenderNote (value) {
var range = this.range();
return range.min <= value && value <= range.max;
};
NumericAxis.prototype.pan = function pan (delta) {
var range = this.translateRange(delta);
return this.limitRange(range.min, range.max, this.totalMin, this.totalMax, range.offset);
};
NumericAxis.prototype.pointsRange = function pointsRange (start, end) {
var startValue = this.getValue(start);
var endValue = this.getValue(end);
var min = Math.min(startValue, endValue);
var max = Math.max(startValue, endValue);
if (this.isValidRange(min, max)) {
return {
min: min,
max: max
};
}
};
NumericAxis.prototype.scaleRange = function scaleRange (scale, cursor) {
var position = Math.abs(this.pointOffset(cursor));
var range = this.options.max - this.options.min;
var delta = this.scaleToDelta(scale, range);
var minDelta = position * delta;
var maxDelta = (1 - position) * delta;
var min = round(this.options.min + minDelta, DEFAULT_PRECISION);
var max = round(this.options.max - maxDelta, DEFAULT_PRECISION);
if (max - min < MIN_VALUE_RANGE) {
max = min + MIN_VALUE_RANGE;
}
return {
min: min,
max: max
};
};
NumericAxis.prototype.zoomRange = function zoomRange (scale, cursor) {
var ref = this;
var totalMin = ref.totalMin;
var totalMax = ref.totalMax;
var range = this.scaleRange(scale, cursor);
return {
min: limitValue(range.min, totalMin, totalMax),
max: limitValue(range.max, totalMin, totalMax),
narrowRange: false
};
};
NumericAxis.prototype.isValidRange = function isValidRange (min, max) {
return max - min > MIN_VALUE_RANGE;
};
return NumericAxis;
}(Axis));
function autoAxisOptions(seriesMin, seriesMax, options) {
var narrowRange = options.narrowRange;
var autoMin = autoAxisMin(seriesMin, seriesMax, narrowRange);
var autoMax = autoAxisMax(seriesMin, seriesMax, narrowRange);
var majorUnit = autoMajorUnit(autoMin, autoMax);
var autoOptions = {
majorUnit: majorUnit
};
if (options.roundToMajorUnit !== false) {
if (autoMin < 0 && remainderClose(autoMin, majorUnit, 1 / 3)) {
autoMin -= majorUnit;
}
if (autoMax > 0 && remainderClose(autoMax, majorUnit, 1 / 3)) {
autoMax += majorUnit;
}
}
autoOptions.min = floor(autoMin, majorUnit);
autoOptions.max = ceil(autoMax, majorUnit);
return autoOptions;
}
function totalAxisOptions(autoOptions, options) {
return {
min: defined(options.min) ? Math.min(autoOptions.min, options.min) : autoOptions.min,
max: defined(options.max) ? Math.max(autoOptions.max, options.max) : autoOptions.max,
majorUnit: autoOptions.majorUnit
};
}
function clearNullValues(options, fields) {
for (var idx = 0; idx < fields.length; idx++) {
var field = fields[idx];
if (options[field] === null) {
options[field] = undefined;
}
}
}
function axisOptions(autoOptions, userOptions) {
var options = userOptions;
var userSetMin, userSetMax;
if (userOptions) {
clearNullValues(userOptions, [ 'min', 'max' ]);
userSetMin = defined(userOptions.min);
userSetMax = defined(userOptions.max);
var userSetLimits = userSetMin || userSetMax;
if (userSetLimits) {
if (userOptions.min === userOptions.max) {
if (userOptions.min > 0) {
userOptions.min = 0;
} else {
userOptions.max = 1;
}
}
}
if (userOptions.majorUnit) {
autoOptions.min = floor(autoOptions.min, userOptions.majorUnit);
autoOptions.max = ceil(autoOptions.max, userOptions.majorUnit);
} else if (userSetLimits) {
options = deepExtend(autoOptions, userOptions);
// Determine an auto major unit after min/max have been set
autoOptions.majorUnit = autoMajorUnit(options.min, options.max);
}
}
autoOptions.minorUnit = (options.majorUnit || autoOptions.majorUnit) / 5;
var result = deepExtend(autoOptions, options);
if (result.min >= result.max) {
if (userSetMin && !userSetMax) {
result.max = result.min + result.majorUnit;
} else if (!userSetMin && userSetMax) {
result.min = result.max - result.majorUnit;
}
}
return result;
}
function remainderClose(value, divisor, ratio) {
var remainder = round(Math.abs(value % divisor), DEFAULT_PRECISION);
var threshold = divisor * (1 - ratio);
return remainder === 0 || remainder > threshold;
}
setDefaultOptions(NumericAxis, {
type: "numeric",
min: 0,
max: 1,
vertical: true,
majorGridLines: {
visible: true,
width: 1,
color: BLACK
},
labels: {
format: "#.####################"
},
zIndex: 1
});
export default NumericAxis;