@progress/kendo-charts 1.31.0 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cdn/js/kendo-charts.js +1 -1
- package/dist/cdn/main.js +1 -1
- package/dist/es/chart/base-theme.js +22 -2
- package/dist/es/chart/categorical-chart.js +6 -26
- package/dist/es/chart/constants.js +11 -1
- package/dist/es/chart/heatmap-chart/heatmap-chart.js +2 -6
- package/dist/es/chart/plotarea/categorical-plotarea.js +83 -16
- package/dist/es/chart/plotarea/plotarea-base.js +71 -2
- package/dist/es/chart/plotarea/plotarea-factory.js +4 -2
- package/dist/es/chart/plotarea/polar-plotarea.js +21 -2
- package/dist/es/chart/plotarea/radar-plotarea.js +13 -2
- package/dist/es/chart/plotarea/xy-plotarea.js +38 -5
- package/dist/es/chart/register-charts.js +12 -7
- package/dist/es/chart/scatter-charts/scatter-chart.js +3 -7
- package/dist/es/chart/trendlines/calculate-moving-average.js +44 -0
- package/dist/es/chart/trendlines/calculate-slope.js +37 -0
- package/dist/es/chart/trendlines/linear-trendline.js +61 -0
- package/dist/es/chart/trendlines/moving-average.js +65 -0
- package/dist/es/chart/trendlines/scatter-linear-trendline.js +63 -0
- package/dist/es/chart/trendlines/scatter-moving-average.js +34 -0
- package/dist/es/chart/trendlines/scatter-trendline-registry.js +9 -0
- package/dist/es/chart/trendlines/scatter-value-getter.js +7 -0
- package/dist/es/chart/trendlines/trendline-factory.js +10 -0
- package/dist/es/chart/trendlines/trendline-registry.js +9 -0
- package/dist/es/chart/utils.js +0 -2
- package/dist/es/common/constants.js +1 -0
- package/dist/es/common/hash-map.js +7 -11
- package/dist/es/core/category-axis.js +37 -30
- package/dist/es/core/date-category-axis.js +27 -3
- package/dist/es2015/chart/base-theme.js +22 -2
- package/dist/es2015/chart/categorical-chart.js +6 -26
- package/dist/es2015/chart/constants.js +11 -1
- package/dist/es2015/chart/heatmap-chart/heatmap-chart.js +2 -6
- package/dist/es2015/chart/plotarea/categorical-plotarea.js +81 -16
- package/dist/es2015/chart/plotarea/plotarea-base.js +69 -2
- package/dist/es2015/chart/plotarea/plotarea-factory.js +4 -2
- package/dist/es2015/chart/plotarea/polar-plotarea.js +21 -2
- package/dist/es2015/chart/plotarea/radar-plotarea.js +13 -2
- package/dist/es2015/chart/plotarea/xy-plotarea.js +36 -5
- package/dist/es2015/chart/register-charts.js +14 -5
- package/dist/es2015/chart/scatter-charts/scatter-chart.js +3 -7
- package/dist/es2015/chart/trendlines/calculate-moving-average.js +42 -0
- package/dist/es2015/chart/trendlines/calculate-slope.js +35 -0
- package/dist/es2015/chart/trendlines/linear-trendline.js +51 -0
- package/dist/es2015/chart/trendlines/moving-average.js +53 -0
- package/dist/es2015/chart/trendlines/scatter-linear-trendline.js +57 -0
- package/dist/es2015/chart/trendlines/scatter-moving-average.js +31 -0
- package/dist/es2015/chart/trendlines/scatter-trendline-registry.js +9 -0
- package/dist/es2015/chart/trendlines/scatter-value-getter.js +4 -0
- package/dist/es2015/chart/trendlines/trendline-factory.js +10 -0
- package/dist/es2015/chart/trendlines/trendline-registry.js +9 -0
- package/dist/es2015/chart/utils.js +0 -2
- package/dist/es2015/common/constants.js +1 -0
- package/dist/es2015/common/hash-map.js +7 -11
- package/dist/es2015/core/category-axis.js +37 -30
- package/dist/es2015/core/date-category-axis.js +27 -3
- package/dist/npm/main.js +889 -353
- package/dist/systemjs/kendo-charts.js +1 -1
- package/package.json +1 -1
|
@@ -4,10 +4,8 @@ import ClipAnimationMixin from '../mixins/clip-animation-mixin';
|
|
|
4
4
|
import ErrorRangeCalculator from '../error-bars/error-range-calculator';
|
|
5
5
|
import ScatterErrorBar from '../error-bars/scatter-error-bar';
|
|
6
6
|
import LinePoint from '../line-chart/line-point';
|
|
7
|
-
import CategoricalChart from '../categorical-chart';
|
|
8
7
|
|
|
9
|
-
import hasValue from '../utils
|
|
10
|
-
import evalOptions from '../utils/eval-options';
|
|
8
|
+
import { hasValue, evalOptions } from '../utils';
|
|
11
9
|
|
|
12
10
|
import { deepExtend, isNumber, isString, defined, isFunction, setDefaultOptions } from '../../common';
|
|
13
11
|
import { X, Y, MIN_VALUE, MAX_VALUE } from '../../common/constants';
|
|
@@ -288,7 +286,7 @@ class ScatterChart extends ChartElement {
|
|
|
288
286
|
}
|
|
289
287
|
|
|
290
288
|
for (let pointIx = 0; pointIx < currentSeries.data.length; pointIx++) {
|
|
291
|
-
const { valueFields: value, fields } = this.
|
|
289
|
+
const { valueFields: value, fields } = this.plotArea.bindPoint(currentSeries, pointIx);
|
|
292
290
|
|
|
293
291
|
callback(value, deepExtend({
|
|
294
292
|
pointIx: pointIx,
|
|
@@ -325,8 +323,6 @@ setDefaultOptions(ScatterChart, {
|
|
|
325
323
|
},
|
|
326
324
|
clip: true
|
|
327
325
|
});
|
|
328
|
-
deepExtend(ScatterChart.prototype, ClipAnimationMixin
|
|
329
|
-
_bindPoint: CategoricalChart.prototype._bindPoint
|
|
330
|
-
});
|
|
326
|
+
deepExtend(ScatterChart.prototype, ClipAnimationMixin);
|
|
331
327
|
|
|
332
328
|
export default ScatterChart;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { MIN_MOVING_AVERAGE_PERIOD } from '../constants';
|
|
2
|
+
|
|
3
|
+
function calculateMovingAverage(sourceValues, valueGetter, period) {
|
|
4
|
+
const averagePoints = [];
|
|
5
|
+
const values = [];
|
|
6
|
+
const start = Math.max(MIN_MOVING_AVERAGE_PERIOD, period) - 1;
|
|
7
|
+
|
|
8
|
+
let end = 0;
|
|
9
|
+
let sum = 0;
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < sourceValues.length; i++) {
|
|
12
|
+
const value = sourceValues[i];
|
|
13
|
+
const { xValue, yValue } = valueGetter(value);
|
|
14
|
+
|
|
15
|
+
if (isFinite(yValue) && yValue !== null) {
|
|
16
|
+
values.push(yValue);
|
|
17
|
+
sum += yValue;
|
|
18
|
+
end = Math.max(i, end);
|
|
19
|
+
} else {
|
|
20
|
+
values.push(null);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (i >= start) {
|
|
24
|
+
const count = values.filter(value => value !== null).length;
|
|
25
|
+
const lastValue = values.shift() || 0;
|
|
26
|
+
|
|
27
|
+
if (count > 0) {
|
|
28
|
+
const average = sum / count;
|
|
29
|
+
averagePoints.push([xValue, average]);
|
|
30
|
+
|
|
31
|
+
sum -= lastValue;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
averagePoints.push([xValue, null]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return averagePoints.slice(0, end + 1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default calculateMovingAverage;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function calculateSlope(sourceValues, valueGetter) {
|
|
2
|
+
let x = 0;
|
|
3
|
+
let y = 0;
|
|
4
|
+
let x2 = 0;
|
|
5
|
+
let xy = 0;
|
|
6
|
+
let count = 0;
|
|
7
|
+
let slope, intercept;
|
|
8
|
+
let xMin = Number.MAX_VALUE;
|
|
9
|
+
let xMax = Number.MIN_VALUE;
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < sourceValues.length; i++) {
|
|
12
|
+
const value = sourceValues[i];
|
|
13
|
+
const { xValue, yValue } = valueGetter(value);
|
|
14
|
+
|
|
15
|
+
if (isFinite(xValue) && xValue !== null && isFinite(yValue) && yValue !== null) {
|
|
16
|
+
xMin = Math.min(xValue, xMin);
|
|
17
|
+
xMax = Math.max(xValue, xMax);
|
|
18
|
+
|
|
19
|
+
count++;
|
|
20
|
+
x += xValue;
|
|
21
|
+
y += yValue;
|
|
22
|
+
x2 += Math.pow(xValue, 2);
|
|
23
|
+
xy += xValue * yValue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (count > 0) {
|
|
28
|
+
slope = (count * xy - x * y) / (count * x2 - Math.pow(x, 2));
|
|
29
|
+
intercept = (y - slope * x) / count;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return { slope, intercept, count, xMin, xMax };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default calculateSlope;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import calculateSlope from './calculate-slope';
|
|
2
|
+
|
|
3
|
+
function linearTrendline(context) {
|
|
4
|
+
const {
|
|
5
|
+
options,
|
|
6
|
+
categoryAxis,
|
|
7
|
+
seriesValues
|
|
8
|
+
} = context;
|
|
9
|
+
|
|
10
|
+
const { data } = getData({ seriesValues, categoryAxis, options });
|
|
11
|
+
if (data) {
|
|
12
|
+
return Object.assign({}, options,
|
|
13
|
+
|
|
14
|
+
{type: 'line',
|
|
15
|
+
data,
|
|
16
|
+
categoryField: 'category',
|
|
17
|
+
field: 'value'});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const valueGetter = fieldName => ({ categoryIx, valueFields }) =>
|
|
24
|
+
({ xValue: categoryIx + 1, yValue: valueFields[fieldName] });
|
|
25
|
+
|
|
26
|
+
function getData({ seriesValues, categoryAxis, options }) {
|
|
27
|
+
const { slope, intercept, count } = calculateSlope(seriesValues(), valueGetter(options.field));
|
|
28
|
+
|
|
29
|
+
if (count > 0) {
|
|
30
|
+
const data = [];
|
|
31
|
+
const totalRange = categoryAxis.totalRangeIndices();
|
|
32
|
+
const currentRange = categoryAxis.currentRangeIndices();
|
|
33
|
+
const range = {
|
|
34
|
+
min: Math.floor(Math.max(currentRange.min - 1, totalRange.min)),
|
|
35
|
+
max: Math.ceil(Math.min(currentRange.max + 2, totalRange.max))
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
for (let i = range.min; i < range.max; i++) {
|
|
39
|
+
data[i] = {
|
|
40
|
+
category: categoryAxis.categoryAt(i, true),
|
|
41
|
+
value: slope * (i + 1) + intercept
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { data };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { data: null };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default linearTrendline;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { MIN_MOVING_AVERAGE_PERIOD } from '../constants';
|
|
2
|
+
import calculateMovingAverage from './calculate-moving-average';
|
|
3
|
+
|
|
4
|
+
function movingAverageTrendline(context) {
|
|
5
|
+
const { options } = context;
|
|
6
|
+
|
|
7
|
+
const { data } = getData(context);
|
|
8
|
+
if (data) {
|
|
9
|
+
return Object.assign({}, options,
|
|
10
|
+
|
|
11
|
+
{type: 'line',
|
|
12
|
+
data,
|
|
13
|
+
categoryField: 'category',
|
|
14
|
+
field: 'value'});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const valueGetter = fieldName => ({ categoryIx, valueFields }) =>
|
|
21
|
+
({ xValue: categoryIx, yValue: valueFields[fieldName] });
|
|
22
|
+
|
|
23
|
+
function calculatePoints({ options, categoryAxis, seriesValues }) {
|
|
24
|
+
const period = (options.trendline || {}).period || MIN_MOVING_AVERAGE_PERIOD;
|
|
25
|
+
const totalRange = categoryAxis.totalRangeIndices();
|
|
26
|
+
const currentRange = categoryAxis.currentRangeIndices();
|
|
27
|
+
const range = {
|
|
28
|
+
min: Math.floor(Math.max(currentRange.min - period, totalRange.min)),
|
|
29
|
+
max: Math.ceil(Math.min(currentRange.max + period + 2, totalRange.max))
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return calculateMovingAverage(seriesValues(range), valueGetter(options.field), period);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getData(context) {
|
|
36
|
+
const { categoryAxis } = context;
|
|
37
|
+
const points = calculatePoints(context);
|
|
38
|
+
const data = [];
|
|
39
|
+
points.forEach(([categoryIx, value]) => {
|
|
40
|
+
data[categoryIx] = {
|
|
41
|
+
category: categoryAxis.categoryAt(categoryIx, true),
|
|
42
|
+
value
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (data.length > 0) {
|
|
47
|
+
return { data };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { data: null };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default movingAverageTrendline;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import autoMajorUnit from '../../core/utils/auto-major-unit';
|
|
2
|
+
import { valueOrDefault } from '../../common';
|
|
3
|
+
import calculateSlope from './calculate-slope';
|
|
4
|
+
import scatterValueGetter from './scatter-value-getter';
|
|
5
|
+
|
|
6
|
+
function scatterLinearTrendLine(context) {
|
|
7
|
+
const {
|
|
8
|
+
options,
|
|
9
|
+
seriesValues
|
|
10
|
+
} = context;
|
|
11
|
+
|
|
12
|
+
const data = getData({ seriesValues, options });
|
|
13
|
+
if (data) {
|
|
14
|
+
return Object.assign({}, options,
|
|
15
|
+
|
|
16
|
+
{type: 'scatterLine',
|
|
17
|
+
data});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getData({ seriesValues, options }) {
|
|
24
|
+
let { slope, intercept, count, xMin, xMax } = calculateSlope(seriesValues(), scatterValueGetter(options.field));
|
|
25
|
+
|
|
26
|
+
if (count > 0) {
|
|
27
|
+
const data = [];
|
|
28
|
+
const forecast = (options.trendline || {}).forecast;
|
|
29
|
+
if (forecast) {
|
|
30
|
+
if (forecast.before > 0) {
|
|
31
|
+
xMin -= forecast.before;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (forecast.after > 0) {
|
|
35
|
+
xMax += forecast.after;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const samplingInterval = (options.trendline || {}).samplingInterval;
|
|
40
|
+
let delta = valueOrDefault(samplingInterval, autoMajorUnit(xMin, xMax) / 10);
|
|
41
|
+
if (samplingInterval <= 0) {
|
|
42
|
+
delta = xMax - xMin;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (let x = xMin; x <= xMax; x += delta) {
|
|
46
|
+
data.push([ x,
|
|
47
|
+
slope * x + intercept
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default scatterLinearTrendLine;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import calculateMovingAverage from './calculate-moving-average';
|
|
2
|
+
import { MIN_MOVING_AVERAGE_PERIOD } from '../constants';
|
|
3
|
+
import scatterValueGetter from './scatter-value-getter';
|
|
4
|
+
|
|
5
|
+
function scatterMovingAverageTrendline(context) {
|
|
6
|
+
const { options } = context;
|
|
7
|
+
|
|
8
|
+
const data = getData(context);
|
|
9
|
+
if (data) {
|
|
10
|
+
return Object.assign({}, options,
|
|
11
|
+
|
|
12
|
+
{type: 'scatterLine',
|
|
13
|
+
data});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getData({ options, seriesValues }) {
|
|
20
|
+
const period = (options.trendline || {}).period || MIN_MOVING_AVERAGE_PERIOD;
|
|
21
|
+
const range = { before: period, after: period };
|
|
22
|
+
const data = calculateMovingAverage(seriesValues(range), scatterValueGetter(options.field), period);
|
|
23
|
+
|
|
24
|
+
if (data.length > 0) {
|
|
25
|
+
return data;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default scatterMovingAverageTrendline;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import scatterLinearTrendLine from './scatter-linear-trendline';
|
|
2
|
+
import scatterMovingAverageTrendline from './scatter-moving-average';
|
|
3
|
+
import { TRENDLINE_LINEAR, TRENDLINE_MOVING_AVERAGE } from '../constants';
|
|
4
|
+
|
|
5
|
+
const scatterRegistry = {};
|
|
6
|
+
scatterRegistry[TRENDLINE_LINEAR] = scatterLinearTrendLine;
|
|
7
|
+
scatterRegistry[TRENDLINE_MOVING_AVERAGE] = scatterMovingAverageTrendline;
|
|
8
|
+
|
|
9
|
+
export default scatterRegistry;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import linearTrendline from './linear-trendline';
|
|
2
|
+
import movingAverageTrendline from './moving-average';
|
|
3
|
+
import { TRENDLINE_LINEAR, TRENDLINE_MOVING_AVERAGE } from '../constants';
|
|
4
|
+
|
|
5
|
+
const registry = {};
|
|
6
|
+
registry[TRENDLINE_LINEAR] = linearTrendline;
|
|
7
|
+
registry[TRENDLINE_MOVING_AVERAGE] = movingAverageTrendline;
|
|
8
|
+
|
|
9
|
+
export default registry;
|
|
@@ -15,5 +15,3 @@ export { default as isDateAxis } from './utils/is-date-axis';
|
|
|
15
15
|
export { default as segmentVisible } from './utils/segment-visible';
|
|
16
16
|
export { default as singleItemOrArray } from './utils/single-item-or-array';
|
|
17
17
|
export { default as createOutOfRangePoints } from './utils/create-out-of-range-points';
|
|
18
|
-
|
|
19
|
-
|
|
@@ -16,6 +16,7 @@ export const FORMAT_REGEX = /\{\d+:?/;
|
|
|
16
16
|
export const HEIGHT = "height";
|
|
17
17
|
export const HIGHLIGHT_ZINDEX = 100;
|
|
18
18
|
export const INSIDE = "inside";
|
|
19
|
+
export const INHERIT = "inherit";
|
|
19
20
|
export const LEFT = "left";
|
|
20
21
|
export const MAX_VALUE = Number.MAX_VALUE;
|
|
21
22
|
export const MIN_VALUE = -Number.MAX_VALUE;
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
// TODO: Remove and replace with Map/WeakMap.
|
|
2
2
|
export default class HashMap {
|
|
3
3
|
constructor() {
|
|
4
|
-
this._map =
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
get(name) {
|
|
8
|
-
return this._map[this._key(name)];
|
|
4
|
+
this._map = new Map();
|
|
9
5
|
}
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
this._map
|
|
7
|
+
get(key) {
|
|
8
|
+
return this._map.get(key);
|
|
13
9
|
}
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
set(key, value) {
|
|
12
|
+
this._map.set(key, value);
|
|
17
13
|
}
|
|
18
|
-
}
|
|
14
|
+
}
|
|
@@ -81,31 +81,6 @@ class CategoryAxis extends Axis {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
totalRangeIndices(limit) {
|
|
85
|
-
const options = this.options;
|
|
86
|
-
let min = isNumber(options.min) ? options.min : 0;
|
|
87
|
-
let max;
|
|
88
|
-
|
|
89
|
-
if (isNumber(options.max)) {
|
|
90
|
-
max = options.max;
|
|
91
|
-
} else if (isNumber(options.min)) {
|
|
92
|
-
max = min + options.categories.length;
|
|
93
|
-
} else {
|
|
94
|
-
max = this.totalRange().max || 1;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (limit) {
|
|
98
|
-
const totalRange = this.totalRange();
|
|
99
|
-
min = limitValue(min, 0, totalRange.max);
|
|
100
|
-
max = limitValue(max, 0, totalRange.max);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
min: min,
|
|
105
|
-
max: max
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
84
|
range() {
|
|
110
85
|
const options = this.options;
|
|
111
86
|
const min = isNumber(options.min) ? options.min : 0;
|
|
@@ -409,7 +384,7 @@ class CategoryAxis extends Axis {
|
|
|
409
384
|
|
|
410
385
|
scaleRange(scale, cursor) {
|
|
411
386
|
const position = Math.abs(this.pointOffset(cursor));
|
|
412
|
-
const rangeIndices = this.
|
|
387
|
+
const rangeIndices = this.limitedRangeIndices();
|
|
413
388
|
const range = rangeIndices.max - rangeIndices.min;
|
|
414
389
|
const delta = this.scaleToDelta(scale, range);
|
|
415
390
|
const minDelta = position * delta;
|
|
@@ -446,7 +421,7 @@ class CategoryAxis extends Axis {
|
|
|
446
421
|
labelsRange() {
|
|
447
422
|
const options = this.options;
|
|
448
423
|
const { justified, labels: labelOptions } = options;
|
|
449
|
-
let { min, max } = this.
|
|
424
|
+
let { min, max } = this.limitedRangeIndices(true);
|
|
450
425
|
const start = Math.floor(min);
|
|
451
426
|
|
|
452
427
|
if (!justified) {
|
|
@@ -483,7 +458,7 @@ class CategoryAxis extends Axis {
|
|
|
483
458
|
}
|
|
484
459
|
|
|
485
460
|
shouldRenderNote(value) {
|
|
486
|
-
const range = this.
|
|
461
|
+
const range = this.limitedRangeIndices();
|
|
487
462
|
|
|
488
463
|
return Math.floor(range.min) <= value && value <= Math.ceil(range.max);
|
|
489
464
|
}
|
|
@@ -516,7 +491,7 @@ class CategoryAxis extends Axis {
|
|
|
516
491
|
}
|
|
517
492
|
|
|
518
493
|
pan(delta) {
|
|
519
|
-
const range = this.
|
|
494
|
+
const range = this.limitedRangeIndices(true);
|
|
520
495
|
const { scale } = this.scaleOptions();
|
|
521
496
|
const offset = round(delta / scale, DEFAULT_PRECISION);
|
|
522
497
|
const totalRange = this.totalRange();
|
|
@@ -529,7 +504,7 @@ class CategoryAxis extends Axis {
|
|
|
529
504
|
pointsRange(start, end) {
|
|
530
505
|
const { reverse, vertical } = this.options;
|
|
531
506
|
const valueAxis = vertical ? Y : X;
|
|
532
|
-
const range = this.
|
|
507
|
+
const range = this.limitedRangeIndices(true);
|
|
533
508
|
const { scale, box } = this.scaleOptions();
|
|
534
509
|
const lineStart = box[valueAxis + (reverse ? 2 : 1)];
|
|
535
510
|
|
|
@@ -582,6 +557,38 @@ class CategoryAxis extends Axis {
|
|
|
582
557
|
};
|
|
583
558
|
}
|
|
584
559
|
|
|
560
|
+
limitedRangeIndices(totalLimit) {
|
|
561
|
+
const options = this.options;
|
|
562
|
+
let min = isNumber(options.min) ? options.min : 0;
|
|
563
|
+
let max;
|
|
564
|
+
|
|
565
|
+
if (isNumber(options.max)) {
|
|
566
|
+
max = options.max;
|
|
567
|
+
} else if (isNumber(options.min)) {
|
|
568
|
+
max = min + options.categories.length;
|
|
569
|
+
} else {
|
|
570
|
+
max = this.totalRange().max || 1;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (totalLimit) {
|
|
574
|
+
const totalRange = this.totalRange();
|
|
575
|
+
min = limitValue(min, 0, totalRange.max);
|
|
576
|
+
max = limitValue(max, 0, totalRange.max);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return {
|
|
580
|
+
min: min,
|
|
581
|
+
max: max
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
totalRangeIndices() {
|
|
586
|
+
return {
|
|
587
|
+
min: 0,
|
|
588
|
+
max: this.totalRange().max || 1
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
585
592
|
mapCategories() {
|
|
586
593
|
if (!this._categoriesMap) {
|
|
587
594
|
const map = this._categoriesMap = new HashMap();
|
|
@@ -20,7 +20,11 @@ const BASE_UNITS = [
|
|
|
20
20
|
const FIT = "fit";
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
function categoryRange(categories) {
|
|
23
|
+
function categoryRange(categories, clearCache) {
|
|
24
|
+
if (clearCache) {
|
|
25
|
+
categories._range = undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
let range = categories._range;
|
|
25
29
|
if (!range) {
|
|
26
30
|
range = categories._range = sparseArrayLimits(categories);
|
|
@@ -360,10 +364,22 @@ class DateCategoryAxis extends CategoryAxis {
|
|
|
360
364
|
options.srcCategories = categories;
|
|
361
365
|
|
|
362
366
|
if (categories.length > 0) {
|
|
363
|
-
const range = categoryRange(categories);
|
|
367
|
+
const range = categoryRange(categories, true);
|
|
364
368
|
const maxDivisions = options.maxDivisions;
|
|
369
|
+
const safeOptions = initUnit(options);
|
|
370
|
+
|
|
371
|
+
const forecast = options._forecast;
|
|
372
|
+
if (forecast) {
|
|
373
|
+
if (forecast.before > 0) {
|
|
374
|
+
range.min = addDuration(range.min, -forecast.before, safeOptions.baseUnit, safeOptions.weekStartDay);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (forecast.after > 0) {
|
|
378
|
+
range.max = addDuration(range.max, forecast.after, safeOptions.baseUnit, safeOptions.weekStartDay);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
365
381
|
|
|
366
|
-
this.dataRange = new DateRange(range.min, range.max,
|
|
382
|
+
this.dataRange = new DateRange(range.min, range.max, safeOptions);
|
|
367
383
|
|
|
368
384
|
if (maxDivisions) {
|
|
369
385
|
const dataRange = this.dataRange.displayRange();
|
|
@@ -876,6 +892,14 @@ class DateCategoryAxis extends CategoryAxis {
|
|
|
876
892
|
return this.dataRange.total();
|
|
877
893
|
}
|
|
878
894
|
|
|
895
|
+
totalRangeIndices() {
|
|
896
|
+
const range = this.dataRange.total();
|
|
897
|
+
return {
|
|
898
|
+
min: this.dataRange.totalIndex(range.min),
|
|
899
|
+
max: this.dataRange.totalIndex(range.max)
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
|
|
879
903
|
totalCount() {
|
|
880
904
|
return this.dataRange.totalCount();
|
|
881
905
|
}
|