@progress/kendo-charts 2.2.0-dev.202401301155 → 2.2.0-dev.202402011056
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/dist/cdn/js/kendo-charts.js +1 -1
- package/dist/cdn/main.js +1 -1
- package/dist/es/sankey/legend.js +59 -0
- package/dist/es/sankey/node.js +3 -1
- package/dist/es/sankey/sankey.js +110 -48
- package/dist/es/sankey/title.js +19 -18
- package/dist/es2015/sankey/legend.js +47 -0
- package/dist/es2015/sankey/node.js +3 -1
- package/dist/es2015/sankey/sankey.js +99 -43
- package/dist/es2015/sankey/title.js +19 -16
- package/dist/npm/main.js +179 -60
- package/dist/systemjs/kendo-charts.js +1 -1
- package/package.json +1 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { drawing } from '@progress/kendo-drawing';
|
|
2
|
-
import { deepExtend, addClass, setDefaultOptions
|
|
2
|
+
import { deepExtend, addClass, setDefaultOptions } from '../common';
|
|
3
3
|
import { calculateSankey } from './calculation';
|
|
4
4
|
import { Node, resolveNodeOptions } from './node';
|
|
5
5
|
import { Link, resolveLinkOptions } from './link';
|
|
6
6
|
import { Label, resolveLabelOptions } from './label';
|
|
7
7
|
import { Title } from './title';
|
|
8
|
-
import {
|
|
8
|
+
import { BOTTOM, LEFT, RIGHT, TOP } from '../common/constants';
|
|
9
9
|
import Box from '../core/box';
|
|
10
10
|
import rectToBox from '../core/utils/rect-to-box';
|
|
11
11
|
import { Observable } from '../common/observable';
|
|
12
|
+
import { Legend } from './legend';
|
|
12
13
|
|
|
13
14
|
const LINK = 'link';
|
|
14
15
|
const NODE = 'node';
|
|
@@ -97,6 +98,7 @@ export class Sankey extends Observable {
|
|
|
97
98
|
const element = ev.element;
|
|
98
99
|
const isLink = element.type === LINK;
|
|
99
100
|
const isNode = element.type === NODE;
|
|
101
|
+
const isLegendItem = Boolean(element.chartElement && element.chartElement.options.node);
|
|
100
102
|
|
|
101
103
|
if ((isLink && this.trigger('linkEnter', ev)) ||
|
|
102
104
|
(isNode && this.trigger('nodeEnter', ev))) {
|
|
@@ -108,10 +110,10 @@ export class Sankey extends Observable {
|
|
|
108
110
|
this.setLinksOpacity(highlight.inactiveOpacity);
|
|
109
111
|
this.setOpacity(element, highlight.opacity);
|
|
110
112
|
} else if (isNode) {
|
|
111
|
-
this.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
this.highlightLinks(element, highlight);
|
|
114
|
+
} else if (isLegendItem) {
|
|
115
|
+
const nodeVisual = this.nodesVisuals.get(element.chartElement.options.node.id);
|
|
116
|
+
this.highlightLinks(nodeVisual, highlight);
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
119
|
|
|
@@ -119,6 +121,7 @@ export class Sankey extends Observable {
|
|
|
119
121
|
const element = ev.element;
|
|
120
122
|
const isLink = element.type === LINK;
|
|
121
123
|
const isNode = element.type === NODE;
|
|
124
|
+
const isLegendItem = Boolean(element.chartElement && element.chartElement.options.node);
|
|
122
125
|
const target = ev.originalEvent.relatedTarget;
|
|
123
126
|
|
|
124
127
|
if (isLink && target && target.nodeName === 'text') {
|
|
@@ -130,11 +133,20 @@ export class Sankey extends Observable {
|
|
|
130
133
|
return;
|
|
131
134
|
}
|
|
132
135
|
|
|
133
|
-
if (isLink || isNode) {
|
|
136
|
+
if (isLink || isNode || isLegendItem) {
|
|
134
137
|
this.setLinksOpacity(this.options.links.opacity);
|
|
135
138
|
}
|
|
136
139
|
}
|
|
137
140
|
|
|
141
|
+
highlightLinks(node, highlight) {
|
|
142
|
+
if (node) {
|
|
143
|
+
this.setLinksOpacity(highlight.inactiveOpacity);
|
|
144
|
+
node.links.forEach(link => {
|
|
145
|
+
this.setOpacity(link, highlight.opacity);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
138
150
|
_destroySurface() {
|
|
139
151
|
if (this.surface) {
|
|
140
152
|
this.surface.destroy();
|
|
@@ -191,22 +203,68 @@ export class Sankey extends Observable {
|
|
|
191
203
|
this.visual = this._render();
|
|
192
204
|
}
|
|
193
205
|
|
|
194
|
-
|
|
195
|
-
if (!title.visible || !title.text) {
|
|
196
|
-
return
|
|
206
|
+
titleBox(title, drawingRect) {
|
|
207
|
+
if (!title || title.visible === false || !title.text) {
|
|
208
|
+
return null;
|
|
197
209
|
}
|
|
198
210
|
|
|
199
|
-
const titleElement = new Title(
|
|
211
|
+
const titleElement = new Title(Object.assign({}, {drawingRect}, title));
|
|
200
212
|
const titleVisual = titleElement.exportVisual();
|
|
201
|
-
return titleVisual.chartElement.box
|
|
213
|
+
return titleVisual.chartElement.box;
|
|
202
214
|
}
|
|
203
215
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
216
|
+
legendBox(options, nodes, drawingRect) {
|
|
217
|
+
if (!options || options.visible === false) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
207
220
|
|
|
221
|
+
const legend = new Legend(Object.assign({}, {nodes}, options, {drawingRect}));
|
|
222
|
+
const legendVisual = legend.exportVisual();
|
|
223
|
+
|
|
224
|
+
return legendVisual.chartElement.box;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
calculateSankey(options) {
|
|
228
|
+
const { title, legend, data } = this.options;
|
|
208
229
|
const { nodes, labels, nodesColors } = this.options;
|
|
209
|
-
|
|
230
|
+
|
|
231
|
+
const sankeyBox = new Box(0, 0, options.width, options.height);
|
|
232
|
+
const titleBox = this.titleBox(title, sankeyBox);
|
|
233
|
+
|
|
234
|
+
let legendArea = sankeyBox.clone();
|
|
235
|
+
|
|
236
|
+
if (titleBox) {
|
|
237
|
+
const titleHeight = titleBox.height();
|
|
238
|
+
if (title.position === TOP) {
|
|
239
|
+
sankeyBox.unpad({ top: titleHeight });
|
|
240
|
+
legendArea = new Box(0, titleHeight, options.width, options.height);
|
|
241
|
+
} else {
|
|
242
|
+
sankeyBox.shrink(0, titleHeight);
|
|
243
|
+
legendArea = new Box(0, 0, options.width, options.height - titleHeight);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const legendBox = this.legendBox(legend, data.nodes, legendArea);
|
|
248
|
+
|
|
249
|
+
if (legendBox) {
|
|
250
|
+
if (legend.position === LEFT) {
|
|
251
|
+
sankeyBox.unpad({ left: legendBox.width() });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (legend.position === RIGHT) {
|
|
255
|
+
sankeyBox.shrink(legendBox.width(), 0);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (legend.position === TOP) {
|
|
259
|
+
sankeyBox.unpad({ top: legendBox.height() });
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (legend.position === BOTTOM) {
|
|
263
|
+
sankeyBox.shrink(0, legendBox.height());
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const calculatedNodes = calculateSankey(Object.assign({}, options, {offsetX: sankeyBox.x1, offsetY: sankeyBox.y1, width: sankeyBox.x2, height: sankeyBox.y2})).nodes;
|
|
210
268
|
const box = new Box();
|
|
211
269
|
|
|
212
270
|
calculatedNodes.forEach((nodeEl, i) => {
|
|
@@ -221,32 +279,40 @@ export class Sankey extends Observable {
|
|
|
221
279
|
}
|
|
222
280
|
});
|
|
223
281
|
|
|
224
|
-
|
|
225
|
-
let offsetY = box.y1 < 0 ? -box.y1 : 0;
|
|
226
|
-
|
|
227
|
-
const width = box.width() > options.width ? offsetX + options.width - (box.width() - options.width) : options.width;
|
|
228
|
-
let height = box.height() > options.height ? offsetY + options.height - (box.height() - options.height) : options.height;
|
|
282
|
+
let offsetX = (box.x1 < 0 ? -box.x1 : 0) + sankeyBox.x1;
|
|
283
|
+
let offsetY = (box.y1 < 0 ? -box.y1 : 0) + sankeyBox.y1;
|
|
229
284
|
|
|
230
|
-
|
|
231
|
-
|
|
285
|
+
let width = box.width() > sankeyBox.x2 ? offsetX + sankeyBox.x2 - (box.width() - sankeyBox.x2) : sankeyBox.x2;
|
|
286
|
+
let height = box.height() > sankeyBox.y2 ? offsetY + sankeyBox.y2 - (box.height() - sankeyBox.y2) : sankeyBox.y2;
|
|
232
287
|
|
|
233
|
-
return
|
|
288
|
+
return {
|
|
289
|
+
sankey: calculateSankey(Object.assign({}, options, {offsetX, offsetY, width, height})),
|
|
290
|
+
legendBox,
|
|
291
|
+
titleBox
|
|
292
|
+
};
|
|
234
293
|
}
|
|
235
294
|
|
|
236
295
|
_render() {
|
|
237
|
-
const { data, labels: labelOptions, nodes: nodesOptions, links: linkOptions, nodesColors, title } = this.options;
|
|
296
|
+
const { data, labels: labelOptions, nodes: nodesOptions, links: linkOptions, nodesColors, title, legend } = this.options;
|
|
238
297
|
const { width, height } = this.size;
|
|
239
|
-
const calcOptions = Object.assign({}, data, {width, height, nodesOptions, title});
|
|
240
|
-
|
|
298
|
+
const calcOptions = Object.assign({}, data, {width, height, nodesOptions, title, legend});
|
|
299
|
+
const { sankey, titleBox, legendBox } = this.calculateSankey(calcOptions);
|
|
300
|
+
const { nodes, links } = sankey;
|
|
241
301
|
|
|
242
302
|
const visual = new drawing.Group();
|
|
243
303
|
|
|
244
|
-
if (
|
|
245
|
-
const titleElement = new Title(
|
|
304
|
+
if (titleBox) {
|
|
305
|
+
const titleElement = new Title(Object.assign({}, title, {drawingRect: titleBox}));
|
|
246
306
|
const titleVisual = titleElement.exportVisual();
|
|
247
307
|
visual.append(titleVisual);
|
|
248
308
|
}
|
|
249
309
|
|
|
310
|
+
if (legendBox) {
|
|
311
|
+
const legendElement = new Legend(Object.assign({}, legend, {drawingRect: legendBox, nodes, colors: nodesColors}));
|
|
312
|
+
const legendVisual = legendElement.exportVisual();
|
|
313
|
+
visual.append(legendVisual);
|
|
314
|
+
}
|
|
315
|
+
|
|
250
316
|
const visualNodes = new Map();
|
|
251
317
|
|
|
252
318
|
nodes.forEach((node, i) => {
|
|
@@ -261,11 +327,11 @@ export class Sankey extends Observable {
|
|
|
261
327
|
visual.append(nodeVisual);
|
|
262
328
|
});
|
|
263
329
|
|
|
264
|
-
|
|
330
|
+
const sortedLinks = links.slice().sort((a, b) => b.value - a.value);
|
|
265
331
|
|
|
266
332
|
const linksVisuals = [];
|
|
267
333
|
|
|
268
|
-
|
|
334
|
+
sortedLinks.forEach(link => {
|
|
269
335
|
const { source, target } = link;
|
|
270
336
|
const sourceNode = visualNodes.get(source.id);
|
|
271
337
|
const targetNode = visualNodes.get(target.id);
|
|
@@ -283,6 +349,7 @@ export class Sankey extends Observable {
|
|
|
283
349
|
});
|
|
284
350
|
|
|
285
351
|
this.linksVisuals = linksVisuals;
|
|
352
|
+
this.nodesVisuals = visualNodes;
|
|
286
353
|
|
|
287
354
|
nodes.forEach((node) => {
|
|
288
355
|
const textOps = resolveLabelOptions(node, labelOptions, width);
|
|
@@ -334,16 +401,5 @@ setDefaultOptions(Sankey, {
|
|
|
334
401
|
opacity: 0.8,
|
|
335
402
|
inactiveOpacity: 0.2
|
|
336
403
|
}
|
|
337
|
-
}
|
|
338
|
-
title: {
|
|
339
|
-
visible: true,
|
|
340
|
-
position: TOP,
|
|
341
|
-
align: CENTER,
|
|
342
|
-
opacity: 1,
|
|
343
|
-
border: {
|
|
344
|
-
width: 0
|
|
345
|
-
},
|
|
346
|
-
margin: getSpacing(5),
|
|
347
|
-
padding: getSpacing(5)
|
|
348
|
-
},
|
|
404
|
+
}
|
|
349
405
|
});
|
|
@@ -1,28 +1,20 @@
|
|
|
1
|
+
import { Title as ChartTitle } from "../core";
|
|
1
2
|
import { SankeyElement } from "./element";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { deepExtend } from "../common";
|
|
5
|
-
import { BOTTOM } from "../common/constants";
|
|
6
|
-
import { getSpacing } from "../common";
|
|
3
|
+
import { setDefaultOptions, getSpacing } from '../common';
|
|
4
|
+
import { CENTER, TOP } from "../common/constants";
|
|
7
5
|
|
|
8
6
|
export class Title extends SankeyElement {
|
|
9
7
|
getElement() {
|
|
10
|
-
const options =
|
|
11
|
-
const {
|
|
12
|
-
const padding = getSpacing(options.padding);
|
|
13
|
-
const margin = getSpacing(options.margin);
|
|
8
|
+
const options = this.options;
|
|
9
|
+
const { drawingRect, text } = options;
|
|
14
10
|
|
|
15
|
-
if (
|
|
11
|
+
if (options.visible === false || !text) {
|
|
16
12
|
return null;
|
|
17
13
|
}
|
|
18
14
|
|
|
19
|
-
const title =
|
|
20
|
-
const titleSizeBox = title.children[0].container.box;
|
|
21
|
-
const totalTitleHeight = margin.top + border.width + padding.top + titleSizeBox.height() + padding.bottom + border.width + margin.bottom;
|
|
22
|
-
const offsetTop = options.position === BOTTOM ? wrapHeight - totalTitleHeight : 0;
|
|
23
|
-
const titleRect = new Box(0, offsetTop, wrapWidth, offsetTop + totalTitleHeight);
|
|
15
|
+
const title = ChartTitle.buildTitle(text, options);
|
|
24
16
|
|
|
25
|
-
title.reflow(
|
|
17
|
+
title.reflow(drawingRect);
|
|
26
18
|
|
|
27
19
|
title.renderVisual();
|
|
28
20
|
return title.visual;
|
|
@@ -32,3 +24,14 @@ export class Title extends SankeyElement {
|
|
|
32
24
|
return this.getElement();
|
|
33
25
|
}
|
|
34
26
|
}
|
|
27
|
+
|
|
28
|
+
setDefaultOptions(Title, {
|
|
29
|
+
position: TOP, // 'top', 'bottom'
|
|
30
|
+
align: CENTER, // 'left', 'right', 'center'
|
|
31
|
+
opacity: 1,
|
|
32
|
+
border: {
|
|
33
|
+
width: 0
|
|
34
|
+
},
|
|
35
|
+
margin: getSpacing(5),
|
|
36
|
+
padding: getSpacing(5)
|
|
37
|
+
});
|