@progress/kendo-charts
Version:
Kendo UI platform-independent Charts library
443 lines (364 loc) • 14.5 kB
JavaScript
import Axis from './axis';
import AxisLabel from './axis-label';
import Box from './box';
import createAxisTick from './utils/create-axis-tick';
import createAxisGridLine from './utils/create-axis-grid-line';
import limitCoordinate from './utils/limit-coordinate';
import { DEFAULT_PRECISION, BLACK } from '../common/constants';
import { deepExtend, defined, inArray, limitValue, round, setDefaultOptions, valueOrDefault } from '../common';
var DEFAULT_MAJOR_UNIT = 10;
var MIN_VALUE_RANGE = 1e-6;
var LogarithmicAxis = (function (Axis) {
function LogarithmicAxis(seriesMin, seriesMax, options, chartService) {
var axisOptions = deepExtend({ majorUnit: DEFAULT_MAJOR_UNIT, min: seriesMin, max: seriesMax }, options);
var base = axisOptions.majorUnit;
var autoMax = autoAxisMax(seriesMax, base);
var autoMin = autoAxisMin(seriesMin, seriesMax, axisOptions);
var range = initRange(autoMin, autoMax, axisOptions, options);
axisOptions.max = range.max;
axisOptions.min = range.min;
axisOptions.minorUnit = options.minorUnit || round(base - 1, DEFAULT_PRECISION);
Axis.call(this, axisOptions, chartService);
this.totalMin = defined(options.min) ? Math.min(autoMin, options.min) : autoMin;
this.totalMax = defined(options.max) ? Math.max(autoMax, options.max) : autoMax;
this.logMin = round(log(range.min, base), DEFAULT_PRECISION);
this.logMax = round(log(range.max, base), DEFAULT_PRECISION);
this.seriesMin = seriesMin;
this.seriesMax = seriesMax;
this.createLabels();
}
if ( Axis ) LogarithmicAxis.__proto__ = Axis;
LogarithmicAxis.prototype = Object.create( Axis && Axis.prototype );
LogarithmicAxis.prototype.constructor = LogarithmicAxis;
LogarithmicAxis.prototype.clone = function clone () {
return new LogarithmicAxis(
this.seriesMin,
this.seriesMax,
Object.assign({}, this.options),
this.chartService
);
};
LogarithmicAxis.prototype.startValue = function startValue () {
return this.options.min;
};
LogarithmicAxis.prototype.getSlot = function getSlot (a, b, limit) {
var ref = this;
var options = ref.options;
var logMin = ref.logMin;
var logMax = ref.logMax;
var base = options.majorUnit;
var min = options.min;
var max = options.max;
var ref$1 = this.lineInfo();
var axis = ref$1.axis;
var axisDir = ref$1.axisDir;
var lineBox = ref$1.lineBox;
var lineSize = ref$1.lineSize;
var lineStart = ref$1.lineStart;
var step = axisDir * (lineSize / (logMax - logMin));
var start = valueOrDefault(a, b || 1);
var end = valueOrDefault(b, a || 1);
if (start <= 0 || end <= 0) {
return null;
}
if (limit) {
start = limitValue(start, min, max);
end = limitValue(end, min, max);
}
start = log(start, base);
end = log(end, base);
var p1 = Math.min(start, end) - logMin;
var p2 = Math.max(start, end) - logMin;
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;
};
LogarithmicAxis.prototype.getValue = function getValue (point) {
var ref = this;
var options = ref.options;
var logMin = ref.logMin;
var logMax = ref.logMax;
var base = options.majorUnit;
var ref$1 = this.lineInfo();
var axis = ref$1.axis;
var axisDir = ref$1.axisDir;
var lineStart = ref$1.lineStart;
var lineSize = ref$1.lineSize;
var step = ((logMax - logMin) / lineSize);
var offset = axisDir * (point[axis] - lineStart);
var valueOffset = offset * step;
if (offset < 0 || offset > lineSize) {
return null;
}
var value = logMin + valueOffset;
return round(Math.pow(base, value), DEFAULT_PRECISION);
};
LogarithmicAxis.prototype.range = function range () {
var options = this.options;
return { min: options.min, max: options.max };
};
LogarithmicAxis.prototype.translateRange = function translateRange (delta) {
var ref = this;
var options = ref.options;
var logMin = ref.logMin;
var logMax = ref.logMax;
var reverse = options.reverse;
var vertical = options.vertical;
var base = options.majorUnit;
var lineBox = this.lineBox();
var size = vertical ? lineBox.height() : lineBox.width();
var scale = size / (logMax - logMin);
var offset = round(delta / scale, DEFAULT_PRECISION);
if ((vertical || reverse) && !(vertical && reverse )) {
offset = -offset;
}
return {
min: Math.pow(base, logMin + offset),
max: Math.pow(base, logMax + offset),
offset: offset
};
};
LogarithmicAxis.prototype.labelsCount = function labelsCount () {
var floorMax = Math.floor(this.logMax);
var count = Math.floor(floorMax - this.logMin) + 1;
return count;
};
LogarithmicAxis.prototype.getMajorTickPositions = function getMajorTickPositions () {
var ticks = [];
this.traverseMajorTicksPositions(function (position) {
ticks.push(position);
}, { step: 1, skip: 0 });
return ticks;
};
LogarithmicAxis.prototype.createTicks = function createTicks (lineGroup) {
var options = this.options;
var majorTicks = options.majorTicks;
var minorTicks = options.minorTicks;
var vertical = options.vertical;
var mirror = options.labels.mirror;
var lineBox = this.lineBox();
var ticks = [];
var tickLineOptions = {
// TODO
// _alignLines: options._alignLines,
vertical: vertical
};
function render(tickPosition, tickOptions) {
tickLineOptions.tickX = mirror ? lineBox.x2 : lineBox.x2 - tickOptions.size;
tickLineOptions.tickY = mirror ? lineBox.y1 - tickOptions.size : lineBox.y1;
tickLineOptions.position = tickPosition;
lineGroup.append(createAxisTick(tickLineOptions, tickOptions));
}
if (majorTicks.visible) {
this.traverseMajorTicksPositions(render, majorTicks);
}
if (minorTicks.visible) {
this.traverseMinorTicksPositions(render, minorTicks);
}
return ticks;
};
LogarithmicAxis.prototype.createGridLines = function createGridLines (altAxis) {
var options = this.options;
var minorGridLines = options.minorGridLines;
var majorGridLines = options.majorGridLines;
var vertical = options.vertical;
var lineBox = altAxis.lineBox();
var lineOptions = {
lineStart: lineBox[vertical ? "x1" : "y1"],
lineEnd: lineBox[vertical ? "x2" : "y2"],
vertical: vertical
};
var majorTicks = [];
var container = this.gridLinesVisual();
function render(tickPosition, gridLine) {
if (!inArray(tickPosition, majorTicks)) {
lineOptions.position = tickPosition;
container.append(createAxisGridLine(lineOptions, gridLine));
majorTicks.push(tickPosition);
}
}
if (majorGridLines.visible) {
this.traverseMajorTicksPositions(render, majorGridLines);
}
if (minorGridLines.visible) {
this.traverseMinorTicksPositions(render, minorGridLines);
}
return container.children;
};
LogarithmicAxis.prototype.traverseMajorTicksPositions = function traverseMajorTicksPositions (callback, tickOptions) {
var ref = this.lineInfo();
var lineStart = ref.lineStart;
var step = ref.step;
var ref$1 = this;
var logMin = ref$1.logMin;
var logMax = ref$1.logMax;
for (var power = Math.ceil(logMin) + tickOptions.skip; power <= logMax; power += tickOptions.step) {
var position = round(lineStart + step * (power - logMin), DEFAULT_PRECISION);
callback(position, tickOptions);
}
};
LogarithmicAxis.prototype.traverseMinorTicksPositions = function traverseMinorTicksPositions (callback, tickOptions) {
var this$1 = this;
var ref = this.options;
var min = ref.min;
var max = ref.max;
var minorUnit = ref.minorUnit;
var base = ref.majorUnit;
var ref$1 = this.lineInfo();
var lineStart = ref$1.lineStart;
var step = ref$1.step;
var ref$2 = this;
var logMin = ref$2.logMin;
var logMax = ref$2.logMax;
var start = Math.floor(logMin);
for (var power = start; power < logMax; power++) {
var minorOptions = this$1._minorIntervalOptions(power);
for (var idx = tickOptions.skip; idx < minorUnit; idx += tickOptions.step) {
var value = minorOptions.value + idx * minorOptions.minorStep;
if (value > max) {
break;
}
if (value >= min) {
var position = round(lineStart + step * (log(value, base) - logMin), DEFAULT_PRECISION);
callback(position, tickOptions);
}
}
}
};
LogarithmicAxis.prototype.createAxisLabel = function createAxisLabel (index, labelOptions, labelContext) {
var power = Math.ceil(this.logMin + index);
var value = Math.pow(this.options.majorUnit, power);
var text = this.axisLabelText(value, labelOptions, labelContext);
return new AxisLabel(value, text, index, null, labelOptions);
};
LogarithmicAxis.prototype.shouldRenderNote = function shouldRenderNote (value) {
var range = this.range();
return range.min <= value && value <= range.max;
};
LogarithmicAxis.prototype.pan = function pan (delta) {
var range = this.translateRange(delta);
return this.limitRange(range.min, range.max, this.totalMin, this.totalMax, range.offset);
};
LogarithmicAxis.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);
return {
min: min,
max: max
};
};
LogarithmicAxis.prototype.scaleRange = function scaleRange (scale, cursor) {
var ref = this.options;
var base = ref.majorUnit;
var logMin = log(this.options.min, base);
var logMax = log(this.options.max, base);
var position = Math.abs(this.pointOffset(cursor));
var range = logMax - logMin;
var delta = this.scaleToDelta(scale, range);
var min = Math.pow(base, logMin + position * delta);
var max = Math.pow(base, logMax - (1 - position) * delta);
if (max - min < MIN_VALUE_RANGE) {
max = min + MIN_VALUE_RANGE;
}
return {
min: min,
max: max
};
};
LogarithmicAxis.prototype.zoomRange = function zoomRange (scale, cursor) {
var range = this.scaleRange(scale, cursor);
var ref = this;
var totalMin = ref.totalMin;
var totalMax = ref.totalMax;
return {
min: limitValue(range.min, totalMin, totalMax),
max: limitValue(range.max, totalMin, totalMax)
};
};
LogarithmicAxis.prototype._minorIntervalOptions = function _minorIntervalOptions (power) {
var ref = this.options;
var minorUnit = ref.minorUnit;
var base = ref.majorUnit;
var value = Math.pow(base, power);
var nextValue = Math.pow(base, power + 1);
var difference = nextValue - value;
var minorStep = difference / minorUnit;
return {
value: value,
minorStep: minorStep
};
};
LogarithmicAxis.prototype.lineInfo = function lineInfo () {
var info = Axis.prototype.lineInfo.call(this);
info.step = info.axisDir * (info.lineSize / (this.logMax - this.logMin));
return info;
};
return LogarithmicAxis;
}(Axis));
function initRange(autoMin, autoMax, axisOptions, options) {
var min = axisOptions.min;
var max = axisOptions.max;
if (defined(axisOptions.axisCrossingValue) && axisOptions.axisCrossingValue <= 0) {
throwNegativeValuesError();
}
if (!defined(options.max)) {
max = autoMax;
} else if (options.max <= 0) {
throwNegativeValuesError();
}
if (!defined(options.min)) {
min = autoMin;
} else if (options.min <= 0) {
throwNegativeValuesError();
}
return {
min: min,
max: max
};
}
function autoAxisMin(min, max, options) {
var base = options.majorUnit;
var autoMin = min;
if (min <= 0) {
autoMin = max <= 1 ? Math.pow(base, -2) : 1;
} else if (!options.narrowRange) {
autoMin = Math.pow(base, Math.floor(log(min, base)));
}
return autoMin;
}
function autoAxisMax(max, base) {
var logMaxRemainder = round(log(max, base), DEFAULT_PRECISION) % 1;
var autoMax;
if (max <= 0) {
autoMax = base;
} else if (logMaxRemainder !== 0 && (logMaxRemainder < 0.3 || logMaxRemainder > 0.9)) {
autoMax = Math.pow(base, log(max, base) + 0.2);
} else {
autoMax = Math.pow(base, Math.ceil(log(max, base)));
}
return autoMax;
}
function throwNegativeValuesError() {
throw new Error("Non positive values cannot be used for a logarithmic axis");
}
function log(x, base) {
return Math.log(x) / Math.log(base);
}
setDefaultOptions(LogarithmicAxis, {
type: "log",
majorUnit: DEFAULT_MAJOR_UNIT,
minorUnit: 1,
axisCrossingValue: 1,
vertical: true,
majorGridLines: {
visible: true,
width: 1,
color: BLACK
},
zIndex: 1,
_deferLabels: true
});
export default LogarithmicAxis;