@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
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import ErrorRangeCalculator from './error-bars/error-range-calculator';
|
|
2
2
|
import CategoricalErrorBar from './error-bars/categorical-error-bar';
|
|
3
3
|
|
|
4
|
-
import SeriesBinder from './series-binder';
|
|
5
4
|
import { ERROR_LOW_FIELD, ERROR_HIGH_FIELD } from './constants';
|
|
6
5
|
|
|
7
|
-
import evalOptions from './utils
|
|
8
|
-
import categoriesCount from './utils/categories-count';
|
|
6
|
+
import { evalOptions, categoriesCount } from './utils';
|
|
9
7
|
|
|
10
8
|
import { ChartElement, Box } from '../core';
|
|
11
9
|
|
|
@@ -420,9 +418,9 @@ class CategoricalChart extends ChartElement {
|
|
|
420
418
|
}
|
|
421
419
|
|
|
422
420
|
limitPoint(point) {
|
|
423
|
-
const
|
|
424
|
-
if (!
|
|
425
|
-
point.reflow(
|
|
421
|
+
const limitedSlot = this.categoryAxis.limitSlot(point.box);
|
|
422
|
+
if (!limitedSlot.equals(point.box)) {
|
|
423
|
+
point.reflow(limitedSlot);
|
|
426
424
|
}
|
|
427
425
|
}
|
|
428
426
|
|
|
@@ -476,7 +474,7 @@ class CategoricalChart extends ChartElement {
|
|
|
476
474
|
for (let seriesIx = 0; seriesIx < seriesCount; seriesIx++) {
|
|
477
475
|
const currentSeries = series[seriesIx];
|
|
478
476
|
const currentCategory = this.categoryAxis.categoryAt(categoryIx);
|
|
479
|
-
const pointData = this.
|
|
477
|
+
const pointData = this.plotArea.bindPoint(currentSeries, categoryIx);
|
|
480
478
|
|
|
481
479
|
callback(pointData, {
|
|
482
480
|
category: currentCategory,
|
|
@@ -497,7 +495,7 @@ class CategoricalChart extends ChartElement {
|
|
|
497
495
|
const outOfRangePoint = series[field];
|
|
498
496
|
if (outOfRangePoint) {
|
|
499
497
|
const categoryIx = outOfRangePoint.categoryIx;
|
|
500
|
-
const pointData = this.
|
|
498
|
+
const pointData = this.plotArea.bindPoint(series, categoryIx, outOfRangePoint.item);
|
|
501
499
|
|
|
502
500
|
callback(pointData, {
|
|
503
501
|
category: outOfRangePoint.category,
|
|
@@ -509,24 +507,6 @@ class CategoricalChart extends ChartElement {
|
|
|
509
507
|
}
|
|
510
508
|
}
|
|
511
509
|
|
|
512
|
-
_bindPoint(series, seriesIx, categoryIx, item) {
|
|
513
|
-
if (!this._bindCache) {
|
|
514
|
-
this._bindCache = [];
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
let bindCache = this._bindCache[seriesIx];
|
|
518
|
-
if (!bindCache) {
|
|
519
|
-
bindCache = this._bindCache[seriesIx] = [];
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
let data = bindCache[categoryIx];
|
|
523
|
-
if (!data) {
|
|
524
|
-
data = bindCache[categoryIx] = SeriesBinder.current.bindPoint(series, categoryIx, item);
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
return data;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
510
|
formatPointValue(point, format) {
|
|
531
511
|
if (point.value === null) {
|
|
532
512
|
return "";
|
|
@@ -62,6 +62,12 @@ const EQUALLY_SPACED_SERIES = [
|
|
|
62
62
|
BULLET, RANGE_COLUMN, RANGE_BAR, WATERFALL, HORIZONTAL_WATERFALL
|
|
63
63
|
];
|
|
64
64
|
|
|
65
|
+
const TRENDLINE_LINEAR = 'linearTrendline';
|
|
66
|
+
const TRENDLINE_MOVING_AVERAGE = 'movingAverageTrendline';
|
|
67
|
+
const TRENDLINE_SERIES = [
|
|
68
|
+
TRENDLINE_LINEAR, TRENDLINE_MOVING_AVERAGE
|
|
69
|
+
];
|
|
70
|
+
|
|
65
71
|
const LEGEND_ITEM_CLICK = "legendItemClick";
|
|
66
72
|
const LEGEND_ITEM_HOVER = "legendItemHover";
|
|
67
73
|
const LEGEND_ITEM_LEAVE = "legendItemLeave";
|
|
@@ -100,6 +106,8 @@ const MOUSEWHEEL_ZOOM_RATE = 0.3;
|
|
|
100
106
|
const DRILLDOWN = "drilldown";
|
|
101
107
|
const DRILLDOWN_FIELD = "drilldown";
|
|
102
108
|
|
|
109
|
+
const MIN_MOVING_AVERAGE_PERIOD = 2;
|
|
110
|
+
|
|
103
111
|
export {
|
|
104
112
|
INITIAL_ANIMATION_DURATION, FADEIN,
|
|
105
113
|
LEGEND_ITEM_CLICK, LEGEND_ITEM_HOVER, LEGEND_ITEM_LEAVE,
|
|
@@ -124,5 +132,7 @@ export {
|
|
|
124
132
|
SHOW_TOOLTIP, HIDE_TOOLTIP,
|
|
125
133
|
EQUALLY_SPACED_SERIES, ABOVE, BELOW,
|
|
126
134
|
HEATMAP,
|
|
127
|
-
DRILLDOWN, DRILLDOWN_FIELD
|
|
135
|
+
DRILLDOWN, DRILLDOWN_FIELD,
|
|
136
|
+
MIN_MOVING_AVERAGE_PERIOD,
|
|
137
|
+
TRENDLINE_SERIES, TRENDLINE_LINEAR, TRENDLINE_MOVING_AVERAGE
|
|
128
138
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { deepExtend, defined, isFunction, setDefaultOptions } from '../../common';
|
|
2
2
|
import { MAX_VALUE, MIN_VALUE } from '../../common/constants';
|
|
3
3
|
import { Box, ChartElement } from '../../core';
|
|
4
|
-
import CategoricalChart from '../categorical-chart';
|
|
5
4
|
import evalOptions from '../utils/eval-options';
|
|
6
5
|
import colorScale from './color-scale';
|
|
7
6
|
import HeatmapPoint from './heatmap-point';
|
|
@@ -36,7 +35,7 @@ class HeatmapChart extends ChartElement {
|
|
|
36
35
|
const currentSeries = series[seriesIx];
|
|
37
36
|
|
|
38
37
|
for (let pointIx = 0; pointIx < currentSeries.data.length; pointIx++) {
|
|
39
|
-
const { valueFields } = this.
|
|
38
|
+
const { valueFields } = this.plotArea.bindPoint(currentSeries, pointIx);
|
|
40
39
|
if (defined(valueFields.value) && valueFields.value !== null) {
|
|
41
40
|
this.valueRange.min = Math.min(this.valueRange.min, valueFields.value);
|
|
42
41
|
this.valueRange.max = Math.max(this.valueRange.max, valueFields.value);
|
|
@@ -191,7 +190,7 @@ class HeatmapChart extends ChartElement {
|
|
|
191
190
|
const yRange = yAxis.currentRangeIndices();
|
|
192
191
|
|
|
193
192
|
for (let pointIx = 0; pointIx < currentSeries.data.length; pointIx++) {
|
|
194
|
-
const { valueFields: value, fields } = this.
|
|
193
|
+
const { valueFields: value, fields } = this.plotArea.bindPoint(currentSeries, pointIx);
|
|
195
194
|
const xIndex = xAxis.totalIndex(value.x);
|
|
196
195
|
const yIndex = yAxis.totalIndex(value.y);
|
|
197
196
|
const xIn = xRange.min <= xIndex && xIndex <= xRange.max;
|
|
@@ -234,8 +233,5 @@ setDefaultOptions(HeatmapChart, {
|
|
|
234
233
|
},
|
|
235
234
|
clip: true
|
|
236
235
|
});
|
|
237
|
-
deepExtend(HeatmapChart.prototype, {
|
|
238
|
-
_bindPoint: CategoricalChart.prototype._bindPoint
|
|
239
|
-
});
|
|
240
236
|
|
|
241
237
|
export default HeatmapChart;
|
|
@@ -14,6 +14,8 @@ import OHLCChart from '../ohlc-chart/ohlc-chart';
|
|
|
14
14
|
import CandlestickChart from '../candlestick-chart/candlestick-chart';
|
|
15
15
|
import BoxPlotChart from '../box-plot-chart/box-plot-chart';
|
|
16
16
|
import WaterfallChart from '../waterfall-chart/waterfall-chart';
|
|
17
|
+
import trendlineFactory from '../trendlines/trendline-factory';
|
|
18
|
+
import trendlineRegistry from '../trendlines/trendline-registry';
|
|
17
19
|
|
|
18
20
|
import { CategoryAxis, DateCategoryAxis, NumericAxis, LogarithmicAxis, Point } from '../../core';
|
|
19
21
|
|
|
@@ -25,7 +27,7 @@ import { BAR, COLUMN, BULLET, VERTICAL_BULLET, LINE, VERTICAL_LINE, AREA, VERTIC
|
|
|
25
27
|
BOX_PLOT, VERTICAL_BOX_PLOT, OHLC, CANDLESTICK, LOGARITHMIC, STEP, EQUALLY_SPACED_SERIES } from '../constants';
|
|
26
28
|
|
|
27
29
|
import { DATE, MAX_VALUE } from '../../common/constants';
|
|
28
|
-
import { setDefaultOptions, inArray,
|
|
30
|
+
import { setDefaultOptions, inArray, deepExtend, defined, eventElement, grep } from '../../common';
|
|
29
31
|
|
|
30
32
|
const AREA_SERIES = [ AREA, VERTICAL_AREA, RANGE_AREA, VERTICAL_RANGE_AREA ];
|
|
31
33
|
const OUT_OF_RANGE_SERIES = [ LINE, VERTICAL_LINE ].concat(AREA_SERIES);
|
|
@@ -36,6 +38,8 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
36
38
|
this.namedCategoryAxes = {};
|
|
37
39
|
this.namedValueAxes = {};
|
|
38
40
|
this.valueAxisRangeTracker = new AxisGroupRangeTracker();
|
|
41
|
+
this._seriesPointsCache = {};
|
|
42
|
+
this._currentPointsCache = {};
|
|
39
43
|
|
|
40
44
|
if (series.length > 0) {
|
|
41
45
|
this.invertAxes = inArray(
|
|
@@ -51,12 +55,15 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
|
-
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
render(panes = this.panes) {
|
|
61
|
+
this.series = [...this.originalSeries];
|
|
58
62
|
this.createCategoryAxes(panes);
|
|
63
|
+
|
|
59
64
|
this.aggregateCategories(panes);
|
|
65
|
+
this.createTrendlineSeries(panes);
|
|
66
|
+
|
|
60
67
|
this.createCategoryAxesLabels(panes);
|
|
61
68
|
this.createCharts(panes);
|
|
62
69
|
this.createValueAxes(panes);
|
|
@@ -83,6 +90,60 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
92
|
|
|
93
|
+
trendlineFactory(options, series) {
|
|
94
|
+
const categoryAxis = this.seriesCategoryAxis(options);
|
|
95
|
+
const seriesValues = this.seriesValues.bind(this, series.index);
|
|
96
|
+
|
|
97
|
+
const trendline = trendlineFactory(trendlineRegistry, options.type, {
|
|
98
|
+
options,
|
|
99
|
+
categoryAxis,
|
|
100
|
+
seriesValues
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (trendline) {
|
|
104
|
+
// Inherit settings
|
|
105
|
+
trendline.categoryAxis = series.categoryAxis;
|
|
106
|
+
trendline.valueAxis = series.valueAxis;
|
|
107
|
+
|
|
108
|
+
return this.filterSeries(trendline, categoryAxis);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return trendline;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
trendlineAggregateForecast() {
|
|
115
|
+
return this.series
|
|
116
|
+
.map(series => (series.trendline || {}).forecast)
|
|
117
|
+
.filter(forecast => forecast !== undefined)
|
|
118
|
+
.reduce((result, forecast) => ({
|
|
119
|
+
before: Math.max(result.before, forecast.before || 0),
|
|
120
|
+
after: Math.max(result.after, forecast.after || 0)
|
|
121
|
+
}), { before: 0, after: 0 });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
seriesValues(seriesIx, range) {
|
|
125
|
+
const result = [];
|
|
126
|
+
|
|
127
|
+
let series = this.srcSeries[seriesIx];
|
|
128
|
+
const categoryAxis = this.seriesCategoryAxis(series);
|
|
129
|
+
const dateAxis = equalsIgnoreCase(categoryAxis.options.type, DATE);
|
|
130
|
+
if (dateAxis) {
|
|
131
|
+
this._seriesPointsCache = {};
|
|
132
|
+
this._currentPointsCache = {};
|
|
133
|
+
categoryAxis.options.dataItems = [];
|
|
134
|
+
series = this.aggregateSeries(series, categoryAxis, categoryAxis.totalRangeIndices());
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const min = range ? range.min : 0;
|
|
138
|
+
const max = range ? range.max : series.data.length;
|
|
139
|
+
for (let categoryIx = min; categoryIx < max; categoryIx++) {
|
|
140
|
+
const data = this.bindPoint(series, categoryIx);
|
|
141
|
+
result.push({ categoryIx, category: data.fields.category, valueFields: data.valueFields });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
|
|
86
147
|
createCharts(panes) {
|
|
87
148
|
const seriesByPane = this.groupSeriesByPane();
|
|
88
149
|
|
|
@@ -146,21 +207,24 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
146
207
|
}
|
|
147
208
|
|
|
148
209
|
aggregateCategories(panes) {
|
|
149
|
-
const series = this.
|
|
210
|
+
const series = [...this.series];
|
|
150
211
|
const processedSeries = [];
|
|
151
212
|
this._currentPointsCache = {};
|
|
152
213
|
this._seriesPointsCache = this._seriesPointsCache || {};
|
|
153
214
|
|
|
154
215
|
for (let i = 0; i < series.length; i++) {
|
|
155
216
|
let currentSeries = series[i];
|
|
156
|
-
const categoryAxis = this.seriesCategoryAxis(currentSeries);
|
|
157
|
-
const axisPane = this.findPane(categoryAxis.options.pane);
|
|
158
|
-
const dateAxis = equalsIgnoreCase(categoryAxis.options.type, DATE);
|
|
159
217
|
|
|
160
|
-
if ((
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
218
|
+
if (!this.isTrendline(currentSeries)) {
|
|
219
|
+
const categoryAxis = this.seriesCategoryAxis(currentSeries);
|
|
220
|
+
const axisPane = this.findPane(categoryAxis.options.pane);
|
|
221
|
+
const dateAxis = equalsIgnoreCase(categoryAxis.options.type, DATE);
|
|
222
|
+
|
|
223
|
+
if ((dateAxis || currentSeries.categoryField) && inArray(axisPane, panes)) {
|
|
224
|
+
currentSeries = this.aggregateSeries(currentSeries, categoryAxis, categoryAxis.currentRangeIndices());
|
|
225
|
+
} else {
|
|
226
|
+
currentSeries = this.filterSeries(currentSeries, categoryAxis);
|
|
227
|
+
}
|
|
164
228
|
}
|
|
165
229
|
|
|
166
230
|
processedSeries.push(currentSeries);
|
|
@@ -177,7 +241,7 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
177
241
|
const dataLength = (series.data || {}).length;
|
|
178
242
|
categoryAxis._seriesMax = Math.max(categoryAxis._seriesMax || 0, dataLength);
|
|
179
243
|
|
|
180
|
-
if (!(
|
|
244
|
+
if (!(defined(categoryAxis.options.min) || defined(categoryAxis.options.max))) {
|
|
181
245
|
return series;
|
|
182
246
|
}
|
|
183
247
|
|
|
@@ -204,7 +268,7 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
204
268
|
|
|
205
269
|
seriesSourcePoints(series, categoryAxis) {
|
|
206
270
|
const key = `${ series.index };${ categoryAxis.categoriesHash() }`;
|
|
207
|
-
if (this._seriesPointsCache[key]) {
|
|
271
|
+
if (this._seriesPointsCache && this._seriesPointsCache[key]) {
|
|
208
272
|
this._currentPointsCache[key] = this._seriesPointsCache[key];
|
|
209
273
|
return this._seriesPointsCache[key];
|
|
210
274
|
}
|
|
@@ -216,7 +280,7 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
216
280
|
const getFn = dateAxis ? getDateField : getField;
|
|
217
281
|
const result = [];
|
|
218
282
|
if (!dateAxis) {
|
|
219
|
-
categoryAxis.mapCategories()
|
|
283
|
+
categoryAxis.mapCategories(); //fixes major performance issue caused by searching for the index for large data
|
|
220
284
|
}
|
|
221
285
|
|
|
222
286
|
for (let idx = 0; idx < srcData.length; idx++) {
|
|
@@ -239,7 +303,7 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
239
303
|
return result;
|
|
240
304
|
}
|
|
241
305
|
|
|
242
|
-
aggregateSeries(series, categoryAxis) {
|
|
306
|
+
aggregateSeries(series, categoryAxis, range) {
|
|
243
307
|
const srcData = series.data;
|
|
244
308
|
if (!srcData.length) {
|
|
245
309
|
return series;
|
|
@@ -249,9 +313,9 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
249
313
|
const result = deepExtend({}, series);
|
|
250
314
|
const aggregator = new SeriesAggregator(deepExtend({}, series), SeriesBinder.current, DefaultAggregates.current);
|
|
251
315
|
const data = result.data = [];
|
|
316
|
+
|
|
252
317
|
const dataItems = categoryAxis.options.dataItems || [];
|
|
253
318
|
|
|
254
|
-
const range = categoryAxis.currentRangeIndices();
|
|
255
319
|
const categoryItem = (idx) => {
|
|
256
320
|
const categoryIdx = idx - range.min;
|
|
257
321
|
let point = srcPoints[idx];
|
|
@@ -594,6 +658,7 @@ class CategoricalPlotArea extends PlotAreaBase {
|
|
|
594
658
|
let categoryAxis;
|
|
595
659
|
|
|
596
660
|
if (isDateAxis(axisOptions, categories[0])) {
|
|
661
|
+
axisOptions._forecast = this.trendlineAggregateForecast();
|
|
597
662
|
categoryAxis = new DateCategoryAxis(axisOptions, this.chartService);
|
|
598
663
|
} else {
|
|
599
664
|
categoryAxis = new CategoryAxis(axisOptions, this.chartService);
|
|
@@ -769,4 +834,4 @@ setDefaultOptions(CategoricalPlotArea, {
|
|
|
769
834
|
|
|
770
835
|
deepExtend(CategoricalPlotArea.prototype, PlotAreaEventsMixin);
|
|
771
836
|
|
|
772
|
-
export default CategoricalPlotArea;
|
|
837
|
+
export default CategoricalPlotArea;
|
|
@@ -4,9 +4,11 @@ import { ChartElement, Box } from '../../core';
|
|
|
4
4
|
import Crosshair from '../crosshair/crosshair';
|
|
5
5
|
import Pane from '../pane';
|
|
6
6
|
import { hasValue } from '../utils';
|
|
7
|
+
import SeriesBinder from '../series-binder';
|
|
7
8
|
|
|
8
|
-
import { WHITE, BLACK, X, Y, COORD_PRECISION, TOP, BOTTOM, LEFT, RIGHT, START, END } from '../../common/constants';
|
|
9
|
-
import { append, deepExtend, defined, getSpacing, getTemplate, inArray, isFunction, isString, limitValue, round, setDefaultOptions } from '../../common';
|
|
9
|
+
import { WHITE, BLACK, X, Y, COORD_PRECISION, TOP, BOTTOM, LEFT, RIGHT, START, END, INHERIT } from '../../common/constants';
|
|
10
|
+
import { append, deepExtend, defined, getSpacing, getTemplate, inArray, isFunction, isString, limitValue, round, setDefaultOptions, last } from '../../common';
|
|
11
|
+
import { TRENDLINE_SERIES } from '../constants';
|
|
10
12
|
|
|
11
13
|
class PlotAreaBase extends ChartElement {
|
|
12
14
|
constructor(series, options, chartService) {
|
|
@@ -22,6 +24,8 @@ class PlotAreaBase extends ChartElement {
|
|
|
22
24
|
this.crosshairs = [];
|
|
23
25
|
this.chartService = chartService;
|
|
24
26
|
this.originalOptions = options;
|
|
27
|
+
this.originalSeries = series;
|
|
28
|
+
this._bindCache = new WeakMap();
|
|
25
29
|
|
|
26
30
|
this.createPanes();
|
|
27
31
|
this.render();
|
|
@@ -38,6 +42,21 @@ class PlotAreaBase extends ChartElement {
|
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
|
|
45
|
+
bindPoint(series, pointIx, item) {
|
|
46
|
+
let cached = this._bindCache.get(series);
|
|
47
|
+
if (!cached) {
|
|
48
|
+
cached = [];
|
|
49
|
+
this._bindCache.set(series, cached);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let data = cached[pointIx];
|
|
53
|
+
if (!data) {
|
|
54
|
+
data = cached[pointIx] = SeriesBinder.current.bindPoint(series, pointIx, item);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return data;
|
|
58
|
+
}
|
|
59
|
+
|
|
41
60
|
createPanes() {
|
|
42
61
|
const titleOptions = this.options.title || {};
|
|
43
62
|
const paneDefaults = this.options.paneDefaults;
|
|
@@ -317,6 +336,8 @@ class PlotAreaBase extends ChartElement {
|
|
|
317
336
|
panesArray[i].empty();
|
|
318
337
|
}
|
|
319
338
|
|
|
339
|
+
this._bindCache = new WeakMap();
|
|
340
|
+
|
|
320
341
|
this.render(panesArray);
|
|
321
342
|
this.detachLabels();
|
|
322
343
|
this.reflowAxes(this.panes);
|
|
@@ -937,6 +958,52 @@ class PlotAreaBase extends ChartElement {
|
|
|
937
958
|
|
|
938
959
|
return labelAxis;
|
|
939
960
|
}
|
|
961
|
+
|
|
962
|
+
isTrendline(series) {
|
|
963
|
+
return series && inArray(series.type, TRENDLINE_SERIES);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
trendlineFactory() { /* abstract */ }
|
|
967
|
+
|
|
968
|
+
createTrendlineSeries() {
|
|
969
|
+
const modifiedSeries = [];
|
|
970
|
+
|
|
971
|
+
this.series = this.series.map(series => {
|
|
972
|
+
if (!this.isTrendline(series)) {
|
|
973
|
+
return series;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
const forSeries = this.seriesByName(series.for);
|
|
977
|
+
if (!forSeries) {
|
|
978
|
+
throw new Error('Invalid Configuration: Unable to locate linked series ' +
|
|
979
|
+
`"${series.for}" for trendline "${series.name}".`);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
const valueFields = SeriesBinder.current.valueFields(forSeries);
|
|
983
|
+
const field = last(valueFields); // Use the last field for multi-field series
|
|
984
|
+
|
|
985
|
+
const trendlineSeries = this.trendlineFactory(Object.assign({}, {field}, series), forSeries);
|
|
986
|
+
if (trendlineSeries) {
|
|
987
|
+
if (forSeries.visible === false) {
|
|
988
|
+
trendlineSeries.visible = false;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
if (trendlineSeries.color === INHERIT) {
|
|
992
|
+
trendlineSeries.color = forSeries.color;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
modifiedSeries.push(trendlineSeries);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
return trendlineSeries;
|
|
999
|
+
}).filter(series => series !== null);
|
|
1000
|
+
|
|
1001
|
+
return modifiedSeries;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
seriesByName(name) {
|
|
1005
|
+
return this.series.find(series => series.name === name);
|
|
1006
|
+
}
|
|
940
1007
|
}
|
|
941
1008
|
|
|
942
1009
|
function isSingleAxis(axis) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import filterSeriesByType from '../utils/filter-series-by-type';
|
|
2
2
|
import { Class } from '../../common';
|
|
3
|
+
import { TRENDLINE_SERIES } from '../constants';
|
|
3
4
|
|
|
4
5
|
class PlotAreaFactory extends Class {
|
|
5
6
|
|
|
@@ -24,8 +25,9 @@ class PlotAreaFactory extends Class {
|
|
|
24
25
|
for (let idx = 0; idx < registry.length; idx++) {
|
|
25
26
|
const entry = registry[idx];
|
|
26
27
|
series = filterSeriesByType(srcSeries, entry.seriesTypes);
|
|
28
|
+
const trendlines = filterSeriesByType(srcSeries, TRENDLINE_SERIES);
|
|
27
29
|
|
|
28
|
-
if (series.length > 0) {
|
|
30
|
+
if ((series.length - trendlines.length) > 0) {
|
|
29
31
|
match = entry;
|
|
30
32
|
break;
|
|
31
33
|
}
|
|
@@ -37,4 +39,4 @@ class PlotAreaFactory extends Class {
|
|
|
37
39
|
|
|
38
40
|
PlotAreaFactory.current = new PlotAreaFactory();
|
|
39
41
|
|
|
40
|
-
export default PlotAreaFactory;
|
|
42
|
+
export default PlotAreaFactory;
|
|
@@ -13,6 +13,7 @@ import filterSeriesByType from '../utils/filter-series-by-type';
|
|
|
13
13
|
|
|
14
14
|
import { ARC } from '../../common/constants';
|
|
15
15
|
import { deepExtend, eventElement, setDefaultOptions } from '../../common';
|
|
16
|
+
import XYPlotArea from './xy-plotarea';
|
|
16
17
|
|
|
17
18
|
class PolarPlotArea extends PolarPlotAreaBase {
|
|
18
19
|
createPolarAxis() {
|
|
@@ -23,6 +24,13 @@ class PolarPlotArea extends PolarPlotAreaBase {
|
|
|
23
24
|
this.appendAxis(polarAxis);
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
render() {
|
|
28
|
+
this.series = [...this.originalSeries];
|
|
29
|
+
this.createTrendlineSeries();
|
|
30
|
+
|
|
31
|
+
super.render();
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
valueAxisOptions(defaults) {
|
|
27
35
|
return deepExtend(defaults, {
|
|
28
36
|
majorGridLines: { type: ARC },
|
|
@@ -35,6 +43,15 @@ class PolarPlotArea extends PolarPlotAreaBase {
|
|
|
35
43
|
this.axisY = this.valueAxis;
|
|
36
44
|
}
|
|
37
45
|
|
|
46
|
+
trendlineFactory(options, series) {
|
|
47
|
+
const trendline = XYPlotArea.prototype.trendlineFactory.call(this, options, series);
|
|
48
|
+
if (trendline) {
|
|
49
|
+
trendline.type = POLAR_LINE;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return trendline;
|
|
53
|
+
}
|
|
54
|
+
|
|
38
55
|
appendChart(chart, pane) {
|
|
39
56
|
this.valueAxisRangeTracker.update(chart.yAxisRanges);
|
|
40
57
|
|
|
@@ -114,6 +131,8 @@ setDefaultOptions(PolarPlotArea, {
|
|
|
114
131
|
yAxis: {}
|
|
115
132
|
});
|
|
116
133
|
|
|
117
|
-
deepExtend(PolarPlotArea.prototype, PlotAreaEventsMixin
|
|
134
|
+
deepExtend(PolarPlotArea.prototype, PlotAreaEventsMixin, {
|
|
135
|
+
seriesValues: XYPlotArea.prototype.seriesValues
|
|
136
|
+
});
|
|
118
137
|
|
|
119
|
-
export default PolarPlotArea;
|
|
138
|
+
export default PolarPlotArea;
|
|
@@ -22,6 +22,7 @@ class RadarPlotArea extends PolarPlotAreaBase {
|
|
|
22
22
|
this.categoryAxis = categoryAxis;
|
|
23
23
|
this.appendAxis(categoryAxis);
|
|
24
24
|
this.aggregateCategories();
|
|
25
|
+
this.createTrendlineSeries();
|
|
25
26
|
this.createCategoryAxesLabels();
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -57,6 +58,15 @@ class RadarPlotArea extends PolarPlotAreaBase {
|
|
|
57
58
|
return currentSeries;
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
trendlineFactory(options, series) {
|
|
62
|
+
const trendline = CategoricalPlotArea.prototype.trendlineFactory.call(this, options, series);
|
|
63
|
+
if (trendline) {
|
|
64
|
+
trendline.type = RADAR_LINE;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return trendline;
|
|
68
|
+
}
|
|
69
|
+
|
|
60
70
|
createCharts() {
|
|
61
71
|
const series = this.filterVisibleSeries(this.series);
|
|
62
72
|
const pane = this.panes[0];
|
|
@@ -153,7 +163,8 @@ class RadarPlotArea extends PolarPlotAreaBase {
|
|
|
153
163
|
deepExtend(RadarPlotArea.prototype, PlotAreaEventsMixin, {
|
|
154
164
|
appendChart: CategoricalPlotArea.prototype.appendChart,
|
|
155
165
|
aggregateSeries: CategoricalPlotArea.prototype.aggregateSeries,
|
|
156
|
-
seriesSourcePoints: CategoricalPlotArea.prototype.seriesSourcePoints
|
|
166
|
+
seriesSourcePoints: CategoricalPlotArea.prototype.seriesSourcePoints,
|
|
167
|
+
seriesValues: CategoricalPlotArea.prototype.seriesValues
|
|
157
168
|
});
|
|
158
169
|
|
|
159
170
|
setDefaultOptions(RadarPlotArea, {
|
|
@@ -163,4 +174,4 @@ setDefaultOptions(RadarPlotArea, {
|
|
|
163
174
|
valueAxis: {}
|
|
164
175
|
});
|
|
165
176
|
|
|
166
|
-
export default RadarPlotArea;
|
|
177
|
+
export default RadarPlotArea;
|
|
@@ -5,12 +5,12 @@ import ScatterChart from '../scatter-charts/scatter-chart';
|
|
|
5
5
|
import ScatterLineChart from '../scatter-charts/scatter-line-chart';
|
|
6
6
|
import BubbleChart from '../bubble-chart/bubble-chart';
|
|
7
7
|
import SeriesBinder from '../series-binder';
|
|
8
|
+
import trendlineFactory from '../trendlines/trendline-factory';
|
|
9
|
+
import scatterTrendlineRegistry from '../trendlines/scatter-trendline-registry';
|
|
8
10
|
|
|
9
11
|
import { NumericAxis, LogarithmicAxis, DateValueAxis, Point } from '../../core';
|
|
10
12
|
|
|
11
|
-
import filterSeriesByType from '../utils
|
|
12
|
-
import equalsIgnoreCase from '../utils/equals-ignore-case';
|
|
13
|
-
import singleItemOrArray from '../utils/single-item-or-array';
|
|
13
|
+
import { filterSeriesByType, equalsIgnoreCase, singleItemOrArray } from '../utils';
|
|
14
14
|
|
|
15
15
|
import { SCATTER, SCATTER_LINE, BUBBLE, LOGARITHMIC } from '../constants';
|
|
16
16
|
|
|
@@ -27,8 +27,10 @@ class XYPlotArea extends PlotAreaBase {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
render(panes = this.panes) {
|
|
30
|
-
|
|
30
|
+
this.series = [...this.originalSeries];
|
|
31
|
+
this.createTrendlineSeries();
|
|
31
32
|
|
|
33
|
+
const seriesByPane = this.groupSeriesByPane();
|
|
32
34
|
for (let i = 0; i < panes.length; i++) {
|
|
33
35
|
const pane = panes[i];
|
|
34
36
|
const paneSeries = seriesByPane[pane.options.name || "default"] || [];
|
|
@@ -251,6 +253,35 @@ class XYPlotArea extends PlotAreaBase {
|
|
|
251
253
|
updateAxisOptions(this.options, index, vertical, options);
|
|
252
254
|
updateAxisOptions(this.originalOptions, index, vertical, options);
|
|
253
255
|
}
|
|
256
|
+
|
|
257
|
+
trendlineFactory(options, series) {
|
|
258
|
+
const seriesValues = this.seriesValues.bind(this, series.index);
|
|
259
|
+
|
|
260
|
+
const trendline = trendlineFactory(scatterTrendlineRegistry, options.type, {
|
|
261
|
+
options,
|
|
262
|
+
seriesValues
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
if (trendline) {
|
|
266
|
+
// Inherit settings
|
|
267
|
+
trendline.xAxis = series.xAxis;
|
|
268
|
+
trendline.yAxis = series.yAxis;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return trendline;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
seriesValues(seriesIx) {
|
|
275
|
+
const result = [];
|
|
276
|
+
const currentSeries = this.series[seriesIx];
|
|
277
|
+
|
|
278
|
+
for (let pointIx = 0; pointIx < currentSeries.data.length; pointIx++) {
|
|
279
|
+
const data = this.bindPoint(currentSeries, pointIx);
|
|
280
|
+
result.push({ pointIx, valueFields: data.valueFields });
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
254
285
|
}
|
|
255
286
|
|
|
256
287
|
function updateAxisOptions(targetOptions, axisIndex, vertical, options) {
|
|
@@ -265,4 +296,4 @@ setDefaultOptions(XYPlotArea, {
|
|
|
265
296
|
|
|
266
297
|
deepExtend(XYPlotArea.prototype, PlotAreaEventsMixin);
|
|
267
298
|
|
|
268
|
-
export default XYPlotArea;
|
|
299
|
+
export default XYPlotArea;
|
|
@@ -15,7 +15,7 @@ import { COLUMN, DONUT, PIE, FUNNEL, PYRAMID, BAR, LINE, VERTICAL_LINE, AREA, VE
|
|
|
15
15
|
RANGE_BAR, WATERFALL, HORIZONTAL_WATERFALL, SCATTER, SCATTER_LINE, BUBBLE,
|
|
16
16
|
POLAR_AREA, POLAR_LINE, POLAR_SCATTER, RADAR_AREA, RADAR_COLUMN, RADAR_LINE, CATEGORY,
|
|
17
17
|
RANGE_AREA, VERTICAL_RANGE_AREA, X_ERROR_LOW_FIELD, X_ERROR_HIGH_FIELD, Y_ERROR_LOW_FIELD, Y_ERROR_HIGH_FIELD,
|
|
18
|
-
ERROR_LOW_FIELD, ERROR_HIGH_FIELD, HEATMAP, DRILLDOWN_FIELD } from './constants';
|
|
18
|
+
ERROR_LOW_FIELD, ERROR_HIGH_FIELD, HEATMAP, DRILLDOWN_FIELD, TRENDLINE_SERIES } from './constants';
|
|
19
19
|
import { X, Y, VALUE } from '../common/constants';
|
|
20
20
|
|
|
21
21
|
const COLOR = "color";
|
|
@@ -30,19 +30,28 @@ const TO = "to";
|
|
|
30
30
|
PlotAreaFactory.current.register(CategoricalPlotArea, [
|
|
31
31
|
BAR, COLUMN, LINE, VERTICAL_LINE, AREA, VERTICAL_AREA,
|
|
32
32
|
CANDLESTICK, OHLC, BULLET, VERTICAL_BULLET, BOX_PLOT, VERTICAL_BOX_PLOT,
|
|
33
|
-
RANGE_COLUMN, RANGE_BAR, WATERFALL, HORIZONTAL_WATERFALL, RANGE_AREA, VERTICAL_RANGE_AREA
|
|
33
|
+
RANGE_COLUMN, RANGE_BAR, WATERFALL, HORIZONTAL_WATERFALL, RANGE_AREA, VERTICAL_RANGE_AREA,
|
|
34
|
+
...TRENDLINE_SERIES
|
|
34
35
|
]);
|
|
35
36
|
|
|
36
37
|
PlotAreaFactory.current.register(XYPlotArea, [
|
|
37
|
-
SCATTER, SCATTER_LINE, BUBBLE
|
|
38
|
+
SCATTER, SCATTER_LINE, BUBBLE,
|
|
39
|
+
...TRENDLINE_SERIES
|
|
38
40
|
]);
|
|
39
41
|
|
|
40
42
|
PlotAreaFactory.current.register(PiePlotArea, [ PIE ]);
|
|
41
43
|
PlotAreaFactory.current.register(DonutPlotArea, [ DONUT ]);
|
|
42
44
|
PlotAreaFactory.current.register(FunnelPlotArea, [ FUNNEL, PYRAMID ]);
|
|
43
45
|
|
|
44
|
-
PlotAreaFactory.current.register(PolarPlotArea, [
|
|
45
|
-
|
|
46
|
+
PlotAreaFactory.current.register(PolarPlotArea, [
|
|
47
|
+
POLAR_AREA, POLAR_LINE, POLAR_SCATTER,
|
|
48
|
+
...TRENDLINE_SERIES
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
PlotAreaFactory.current.register(RadarPlotArea, [
|
|
52
|
+
RADAR_AREA, RADAR_COLUMN, RADAR_LINE,
|
|
53
|
+
...TRENDLINE_SERIES
|
|
54
|
+
]);
|
|
46
55
|
|
|
47
56
|
PlotAreaFactory.current.register(HeatmapPlotArea, [ HEATMAP ]);
|
|
48
57
|
|