@amcharts/amcharts5-mcp 1.0.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/.gitmodules +3 -0
- package/README.md +82 -0
- package/amcharts5-skill/README.md +50 -0
- package/amcharts5-skill/amcharts5-skill/SKILL.md +667 -0
- package/amcharts5-skill/amcharts5-skill/references/flow.md +523 -0
- package/amcharts5-skill/amcharts5-skill/references/gantt.md +410 -0
- package/amcharts5-skill/amcharts5-skill/references/hierarchy.md +568 -0
- package/amcharts5-skill/amcharts5-skill/references/map.md +574 -0
- package/amcharts5-skill/amcharts5-skill/references/pie.md +663 -0
- package/amcharts5-skill/amcharts5-skill/references/radar.md +584 -0
- package/amcharts5-skill/amcharts5-skill/references/stock.md +664 -0
- package/amcharts5-skill/amcharts5-skill/references/timeline.md +449 -0
- package/amcharts5-skill/amcharts5-skill/references/ui-elements.md +393 -0
- package/amcharts5-skill/amcharts5-skill/references/venn.md +368 -0
- package/amcharts5-skill/amcharts5-skill/references/wordcloud.md +339 -0
- package/amcharts5-skill/amcharts5-skill/references/xy.md +1150 -0
- package/amcharts5-skill/cursorrules +820 -0
- package/package.json +27 -0
- package/src/index.js +329 -0
- package/test.js +153 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
# Flow Charts — Sankey, Chord, Arc Diagrams
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## Required imports
|
|
5
|
+
|
|
6
|
+
### ES modules
|
|
7
|
+
```ts
|
|
8
|
+
import * as am5 from "@amcharts/amcharts5";
|
|
9
|
+
import * as am5flow from "@amcharts/amcharts5/flow";
|
|
10
|
+
import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### CDN
|
|
14
|
+
```html
|
|
15
|
+
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
|
|
16
|
+
<script src="https://cdn.amcharts.com/lib/5/flow.js"></script>
|
|
17
|
+
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Data structure (shared by all flow types)
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
var data = [
|
|
24
|
+
{ from: "A", to: "D", value: 10 },
|
|
25
|
+
{ from: "B", to: "D", value: 8 },
|
|
26
|
+
{ from: "B", to: "E", value: 4 },
|
|
27
|
+
{ from: "C", to: "E", value: 3 },
|
|
28
|
+
{ from: "D", to: "F", value: 15 },
|
|
29
|
+
{ from: "E", to: "F", value: 6 }
|
|
30
|
+
];
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Node IDs ("A", "B", etc.) are automatically extracted — you don't define nodes separately.
|
|
34
|
+
|
|
35
|
+
## Series types
|
|
36
|
+
|
|
37
|
+
| Class | Use for | Visual |
|
|
38
|
+
|-------|---------|--------|
|
|
39
|
+
| `am5flow.Sankey` | Linear flow diagrams | Rectangular nodes + curved links |
|
|
40
|
+
| `am5flow.Chord` | Circular relationship diagrams | Arc nodes + ribbon links |
|
|
41
|
+
| `am5flow.ChordDirected` | Directed chord (arrows) | Arc nodes + directed ribbons |
|
|
42
|
+
| `am5flow.ChordNonRibbon` | Chord with line links | Arc nodes + line links |
|
|
43
|
+
| `am5flow.ArcDiagram` | Arc connections between linear nodes | Linear nodes + arc links |
|
|
44
|
+
|
|
45
|
+
## Sankey diagram
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
const root = am5.Root.new("chartdiv");
|
|
49
|
+
root.setThemes([am5themes_Animated.new(root)]);
|
|
50
|
+
|
|
51
|
+
const series = root.container.children.push(
|
|
52
|
+
am5flow.Sankey.new(root, {
|
|
53
|
+
sourceIdField: "from",
|
|
54
|
+
targetIdField: "to",
|
|
55
|
+
valueField: "value",
|
|
56
|
+
orientation: "horizontal", // "horizontal" (default) or "vertical"
|
|
57
|
+
nodeAlign: "justify", // "left" | "right" | "center" | "justify"
|
|
58
|
+
nodeWidth: 10, // pixel width of nodes
|
|
59
|
+
nodePadding: 10, // pixel gap between nodes
|
|
60
|
+
minSize: 0.01 // min node size as fraction of total
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Node appearance
|
|
65
|
+
series.nodes.rectangles.template.setAll({
|
|
66
|
+
fillOpacity: 1,
|
|
67
|
+
stroke: am5.color(0x000000),
|
|
68
|
+
strokeWidth: 1,
|
|
69
|
+
cornerRadiusTL: 4,
|
|
70
|
+
cornerRadiusTR: 4,
|
|
71
|
+
cornerRadiusBL: 4,
|
|
72
|
+
cornerRadiusBR: 4
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Disable node dragging (optional)
|
|
76
|
+
series.nodes.nodes.template.setAll({
|
|
77
|
+
draggable: false,
|
|
78
|
+
toggleKey: "none"
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Link appearance
|
|
82
|
+
series.links.template.setAll({
|
|
83
|
+
fillOpacity: 0.3,
|
|
84
|
+
strokeOpacity: 0,
|
|
85
|
+
tooltipText: "{sourceId} → {targetId}: {value}"
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Node labels
|
|
89
|
+
series.nodes.labels.template.setAll({
|
|
90
|
+
text: "{name}",
|
|
91
|
+
fontSize: 12,
|
|
92
|
+
fill: am5.color(0x000000)
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Node tooltip
|
|
96
|
+
series.nodes.nodes.template.set("tooltipText", "{name}: {sumIncoming} in / {sumOutgoing} out");
|
|
97
|
+
|
|
98
|
+
// Data — LAST
|
|
99
|
+
series.data.setAll(data);
|
|
100
|
+
series.appear(1000);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Sankey key settings
|
|
104
|
+
|
|
105
|
+
| Setting | Type | Description |
|
|
106
|
+
|---------|------|-------------|
|
|
107
|
+
| `sourceIdField` | string | Data field for source node ID (required) |
|
|
108
|
+
| `targetIdField` | string | Data field for target node ID (required) |
|
|
109
|
+
| `valueField` | string | Data field for link value (required) |
|
|
110
|
+
| `orientation` | `"horizontal" \| "vertical"` | Flow direction |
|
|
111
|
+
| `nodeAlign` | `"left" \| "right" \| "center" \| "justify"` | Node alignment |
|
|
112
|
+
| `nodeWidth` | number | Width of nodes in pixels (default: 10) |
|
|
113
|
+
| `nodePadding` | number | Gap between nodes (default: 10) |
|
|
114
|
+
| `linkSort` | function \| null | Custom link sort, `null` for no sorting |
|
|
115
|
+
|
|
116
|
+
## Chord diagram
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
const series = root.container.children.push(
|
|
120
|
+
am5flow.Chord.new(root, {
|
|
121
|
+
sourceIdField: "from",
|
|
122
|
+
targetIdField: "to",
|
|
123
|
+
valueField: "value",
|
|
124
|
+
nodeWidth: 20,
|
|
125
|
+
padAngle: 2, // gap between nodes in degrees
|
|
126
|
+
radius: am5.percent(90),
|
|
127
|
+
startAngle: 80,
|
|
128
|
+
sort: "ascending" // "ascending" | "descending" | "none"
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Node appearance (slices on the ring)
|
|
133
|
+
series.nodes.rectangles.template.setAll({
|
|
134
|
+
fillOpacity: 0.8,
|
|
135
|
+
stroke: am5.color(0xffffff),
|
|
136
|
+
strokeWidth: 2
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Link appearance
|
|
140
|
+
series.links.template.setAll({
|
|
141
|
+
fillOpacity: 0.3,
|
|
142
|
+
tooltipText: "{sourceId} → {targetId}: {value}"
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
series.data.setAll(data);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### ChordDirected (with arrows)
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
const series = root.container.children.push(
|
|
152
|
+
am5flow.ChordDirected.new(root, {
|
|
153
|
+
sourceIdField: "from",
|
|
154
|
+
targetIdField: "to",
|
|
155
|
+
valueField: "value"
|
|
156
|
+
})
|
|
157
|
+
);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### ChordNonRibbon (thin lines)
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
const series = root.container.children.push(
|
|
164
|
+
am5flow.ChordNonRibbon.new(root, {
|
|
165
|
+
sourceIdField: "from",
|
|
166
|
+
targetIdField: "to",
|
|
167
|
+
valueField: "value"
|
|
168
|
+
})
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Line appearance
|
|
172
|
+
series.links.template.setAll({
|
|
173
|
+
strokeOpacity: 0.5,
|
|
174
|
+
fillOpacity: 0,
|
|
175
|
+
strokeWidth: 2
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Arc diagram
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
const series = root.container.children.push(
|
|
183
|
+
am5flow.ArcDiagram.new(root, {
|
|
184
|
+
sourceIdField: "from",
|
|
185
|
+
targetIdField: "to",
|
|
186
|
+
valueField: "value",
|
|
187
|
+
orientation: "horizontal"
|
|
188
|
+
})
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
series.links.template.setAll({
|
|
192
|
+
strokeOpacity: 0.3,
|
|
193
|
+
fillOpacity: 0,
|
|
194
|
+
strokeWidth: 1
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
series.data.setAll(data);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Custom node data and colors
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
// Define explicit node data with colors and custom names
|
|
204
|
+
series.nodes.data.setAll([
|
|
205
|
+
{ id: "A", name: "Source A", fill: am5.color(0x095256) },
|
|
206
|
+
{ id: "B", name: "Target B", fill: am5.color(0x087f8c) },
|
|
207
|
+
{ id: "C", name: "Output C", fill: am5.color(0x5aaa95) }
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
// Apply node colors from data
|
|
211
|
+
series.nodes.rectangles.template.adapters.add("fill", function(fill, target) {
|
|
212
|
+
var dataItem = target.dataItem;
|
|
213
|
+
if (dataItem && dataItem.dataContext && dataItem.dataContext.fill) {
|
|
214
|
+
return dataItem.dataContext.fill;
|
|
215
|
+
}
|
|
216
|
+
return fill;
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Node labels use the "name" field by default
|
|
220
|
+
series.nodes.labels.template.setAll({
|
|
221
|
+
text: "{name}"
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Multi-level Sankey (3+ levels)
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
// Data with 3 levels: Source → Category → Destination
|
|
229
|
+
var data = [
|
|
230
|
+
{ from: "Solar", to: "Renewable", value: 30 },
|
|
231
|
+
{ from: "Wind", to: "Renewable", value: 25 },
|
|
232
|
+
{ from: "Coal", to: "Fossil", value: 40 },
|
|
233
|
+
{ from: "Gas", to: "Fossil", value: 35 },
|
|
234
|
+
{ from: "Renewable", to: "Residential", value: 20 },
|
|
235
|
+
{ from: "Renewable", to: "Commercial", value: 35 },
|
|
236
|
+
{ from: "Fossil", to: "Residential", value: 30 },
|
|
237
|
+
{ from: "Fossil", to: "Industrial", value: 45 }
|
|
238
|
+
];
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Events on flow elements
|
|
242
|
+
|
|
243
|
+
```js
|
|
244
|
+
// Node click
|
|
245
|
+
series.nodes.nodes.template.events.on("click", function(ev) {
|
|
246
|
+
console.log("Node:", ev.target.dataItem.get("id"));
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Link click
|
|
250
|
+
series.links.template.events.on("click", function(ev) {
|
|
251
|
+
console.log("Link:", ev.target.dataItem.dataContext);
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Animated bullets along links
|
|
256
|
+
|
|
257
|
+
Animated labels/circles that flow along Sankey or Chord links use `series.bullets.push()` — **NOT** `series.links.template.bullets.push()`. The bullet position (0 = source, 1 = target) is animated in a loop, and an adapter fades opacity based on position.
|
|
258
|
+
|
|
259
|
+
**Important:** Sankey uses `locationX`, Chord uses `locationY`.
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
series.bullets.push(function(root, series, dataItem) {
|
|
263
|
+
var label = am5.Label.new(root, {
|
|
264
|
+
text: "${value}B",
|
|
265
|
+
populateText: true,
|
|
266
|
+
centerX: am5.p50,
|
|
267
|
+
fill: am5.color(0xffffff),
|
|
268
|
+
fontSize: 11
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
var bullet = am5.Bullet.new(root, {
|
|
272
|
+
locationX: 0,
|
|
273
|
+
sprite: label,
|
|
274
|
+
autoRotate: true // orient along link direction
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Animate position along the link: 0 → 1, looping forever
|
|
278
|
+
bullet.animate({
|
|
279
|
+
key: "locationX",
|
|
280
|
+
from: 0,
|
|
281
|
+
to: 1,
|
|
282
|
+
duration: Math.random() * 10000 + 2000,
|
|
283
|
+
loops: Infinity
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// Fade in at center, fade out at edges via adapter
|
|
287
|
+
label.adapters.add("opacity", function(opacity) {
|
|
288
|
+
return 0.5 - Math.abs(0.5 - bullet.get("locationX"));
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Drive the adapter on every position change
|
|
292
|
+
bullet.on("locationX", function() {
|
|
293
|
+
label.set("opacity", label.get("opacity"));
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
return bullet;
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**For Chord diagrams**, replace every `locationX` with `locationY`:
|
|
301
|
+
|
|
302
|
+
```js
|
|
303
|
+
var bullet = am5.Bullet.new(root, {
|
|
304
|
+
locationY: 0,
|
|
305
|
+
sprite: label,
|
|
306
|
+
autoRotate: true
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
bullet.animate({
|
|
310
|
+
key: "locationY",
|
|
311
|
+
from: 0, to: 1,
|
|
312
|
+
duration: Math.random() * 10000 + 2000,
|
|
313
|
+
loops: Infinity
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
label.adapters.add("opacity", function(opacity) {
|
|
317
|
+
return 0.5 - Math.abs(0.5 - bullet.get("locationY"));
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
bullet.on("locationY", function() {
|
|
321
|
+
label.set("opacity", label.get("opacity"));
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Key points:**
|
|
326
|
+
- Use `series.bullets.push()` — bullets belong to the series, not to `series.links.template`
|
|
327
|
+
- **Sankey → `locationX`**, **Chord → `locationY`** (using the wrong one means bullets won't animate)
|
|
328
|
+
- `autoRotate: true` makes the label follow the link curve
|
|
329
|
+
- Random duration per bullet creates natural asynchronous flow
|
|
330
|
+
- The opacity adapter formula `0.5 - Math.abs(0.5 - location)` gives a bell curve: invisible at edges, max at center
|
|
331
|
+
- `bullet.on("locationX"/"locationY", ...)` is needed to trigger the adapter as position changes
|
|
332
|
+
|
|
333
|
+
## Disposal
|
|
334
|
+
|
|
335
|
+
```js
|
|
336
|
+
root.dispose();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
# amCharts 5 Flow Charts — Working Examples
|
|
343
|
+
|
|
344
|
+
## Example 1: Sankey diagram
|
|
345
|
+
|
|
346
|
+
```html
|
|
347
|
+
<!DOCTYPE html>
|
|
348
|
+
<html>
|
|
349
|
+
<head>
|
|
350
|
+
<meta charset="UTF-8">
|
|
351
|
+
<title>Sankey Diagram</title>
|
|
352
|
+
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
|
|
353
|
+
<script src="https://cdn.amcharts.com/lib/5/flow.js"></script>
|
|
354
|
+
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
|
|
355
|
+
<style>#chartdiv { width: 100%; height: 500px; }</style>
|
|
356
|
+
</head>
|
|
357
|
+
<body>
|
|
358
|
+
<div id="chartdiv"></div>
|
|
359
|
+
<script>
|
|
360
|
+
var root = am5.Root.new("chartdiv");
|
|
361
|
+
root.setThemes([am5themes_Animated.new(root)]);
|
|
362
|
+
|
|
363
|
+
var series = root.container.children.push(am5flow.Sankey.new(root, {
|
|
364
|
+
sourceIdField: "from",
|
|
365
|
+
targetIdField: "to",
|
|
366
|
+
valueField: "value",
|
|
367
|
+
nodeAlign: "justify",
|
|
368
|
+
nodeWidth: 12,
|
|
369
|
+
nodePadding: 15
|
|
370
|
+
}));
|
|
371
|
+
|
|
372
|
+
series.nodes.rectangles.template.setAll({
|
|
373
|
+
fillOpacity: 1,
|
|
374
|
+
stroke: am5.color(0xffffff),
|
|
375
|
+
strokeWidth: 1,
|
|
376
|
+
cornerRadiusTL: 2, cornerRadiusTR: 2,
|
|
377
|
+
cornerRadiusBL: 2, cornerRadiusBR: 2
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
series.links.template.setAll({
|
|
381
|
+
fillOpacity: 0.3,
|
|
382
|
+
tooltipText: "{sourceId} → {targetId}\n[bold]{value}[/]"
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
series.nodes.labels.template.setAll({
|
|
386
|
+
fontSize: 13,
|
|
387
|
+
fill: am5.color(0x333333)
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
series.data.setAll([
|
|
391
|
+
{ from: "Website", to: "Sign Up", value: 5000 },
|
|
392
|
+
{ from: "Website", to: "Bounce", value: 3000 },
|
|
393
|
+
{ from: "Social Media", to: "Sign Up", value: 2000 },
|
|
394
|
+
{ from: "Social Media", to: "Bounce", value: 1500 },
|
|
395
|
+
{ from: "Email", to: "Sign Up", value: 1000 },
|
|
396
|
+
{ from: "Sign Up", to: "Free Trial", value: 4800 },
|
|
397
|
+
{ from: "Sign Up", to: "Abandoned", value: 3200 },
|
|
398
|
+
{ from: "Free Trial", to: "Paid", value: 2400 },
|
|
399
|
+
{ from: "Free Trial", to: "Cancelled", value: 2400 }
|
|
400
|
+
]);
|
|
401
|
+
|
|
402
|
+
series.appear(1000, 100);
|
|
403
|
+
</script>
|
|
404
|
+
</body>
|
|
405
|
+
</html>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## Example 2: Chord diagram
|
|
409
|
+
|
|
410
|
+
```html
|
|
411
|
+
<!DOCTYPE html>
|
|
412
|
+
<html>
|
|
413
|
+
<head>
|
|
414
|
+
<meta charset="UTF-8">
|
|
415
|
+
<title>Chord Diagram</title>
|
|
416
|
+
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
|
|
417
|
+
<script src="https://cdn.amcharts.com/lib/5/flow.js"></script>
|
|
418
|
+
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
|
|
419
|
+
<style>#chartdiv { width: 100%; height: 600px; }</style>
|
|
420
|
+
</head>
|
|
421
|
+
<body>
|
|
422
|
+
<div id="chartdiv"></div>
|
|
423
|
+
<script>
|
|
424
|
+
var root = am5.Root.new("chartdiv");
|
|
425
|
+
root.setThemes([am5themes_Animated.new(root)]);
|
|
426
|
+
|
|
427
|
+
var series = root.container.children.push(am5flow.Chord.new(root, {
|
|
428
|
+
sourceIdField: "from",
|
|
429
|
+
targetIdField: "to",
|
|
430
|
+
valueField: "value",
|
|
431
|
+
nodeWidth: 15,
|
|
432
|
+
padAngle: 3
|
|
433
|
+
}));
|
|
434
|
+
|
|
435
|
+
series.nodes.rectangles.template.setAll({
|
|
436
|
+
fillOpacity: 0.9,
|
|
437
|
+
stroke: am5.color(0xffffff),
|
|
438
|
+
strokeWidth: 2
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
series.links.template.setAll({
|
|
442
|
+
fillOpacity: 0.2,
|
|
443
|
+
tooltipText: "{sourceId} ↔ {targetId}: {value}"
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
series.nodes.labels.template.setAll({
|
|
447
|
+
textType: "radial",
|
|
448
|
+
fontSize: 13
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
series.data.setAll([
|
|
452
|
+
{ from: "US", to: "China", value: 120 },
|
|
453
|
+
{ from: "US", to: "EU", value: 200 },
|
|
454
|
+
{ from: "US", to: "Japan", value: 80 },
|
|
455
|
+
{ from: "China", to: "EU", value: 150 },
|
|
456
|
+
{ from: "China", to: "Japan", value: 90 },
|
|
457
|
+
{ from: "EU", to: "Japan", value: 60 },
|
|
458
|
+
{ from: "US", to: "India", value: 70 },
|
|
459
|
+
{ from: "China", to: "India", value: 110 },
|
|
460
|
+
{ from: "EU", to: "India", value: 40 }
|
|
461
|
+
]);
|
|
462
|
+
|
|
463
|
+
series.appear(1000, 100);
|
|
464
|
+
</script>
|
|
465
|
+
</body>
|
|
466
|
+
</html>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Example 3: Vertical Sankey
|
|
470
|
+
|
|
471
|
+
```html
|
|
472
|
+
<!DOCTYPE html>
|
|
473
|
+
<html>
|
|
474
|
+
<head>
|
|
475
|
+
<meta charset="UTF-8">
|
|
476
|
+
<title>Vertical Sankey</title>
|
|
477
|
+
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
|
|
478
|
+
<script src="https://cdn.amcharts.com/lib/5/flow.js"></script>
|
|
479
|
+
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
|
|
480
|
+
<style>#chartdiv { width: 100%; height: 600px; }</style>
|
|
481
|
+
</head>
|
|
482
|
+
<body>
|
|
483
|
+
<div id="chartdiv"></div>
|
|
484
|
+
<script>
|
|
485
|
+
var root = am5.Root.new("chartdiv");
|
|
486
|
+
root.setThemes([am5themes_Animated.new(root)]);
|
|
487
|
+
|
|
488
|
+
var series = root.container.children.push(am5flow.Sankey.new(root, {
|
|
489
|
+
sourceIdField: "from",
|
|
490
|
+
targetIdField: "to",
|
|
491
|
+
valueField: "value",
|
|
492
|
+
orientation: "vertical",
|
|
493
|
+
nodeAlign: "center",
|
|
494
|
+
nodeWidth: 8,
|
|
495
|
+
nodePadding: 20
|
|
496
|
+
}));
|
|
497
|
+
|
|
498
|
+
series.nodes.rectangles.template.setAll({
|
|
499
|
+
fillOpacity: 1, strokeOpacity: 0
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
series.links.template.setAll({
|
|
503
|
+
fillOpacity: 0.25,
|
|
504
|
+
tooltipText: "{sourceId} → {targetId}: {value}"
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
series.data.setAll([
|
|
508
|
+
{ from: "Total Budget", to: "Marketing", value: 300 },
|
|
509
|
+
{ from: "Total Budget", to: "Engineering", value: 500 },
|
|
510
|
+
{ from: "Total Budget", to: "Operations", value: 200 },
|
|
511
|
+
{ from: "Marketing", to: "Digital Ads", value: 150 },
|
|
512
|
+
{ from: "Marketing", to: "Content", value: 100 },
|
|
513
|
+
{ from: "Marketing", to: "Events", value: 50 },
|
|
514
|
+
{ from: "Engineering", to: "Frontend", value: 200 },
|
|
515
|
+
{ from: "Engineering", to: "Backend", value: 200 },
|
|
516
|
+
{ from: "Engineering", to: "Infra", value: 100 }
|
|
517
|
+
]);
|
|
518
|
+
|
|
519
|
+
series.appear(1000, 100);
|
|
520
|
+
</script>
|
|
521
|
+
</body>
|
|
522
|
+
</html>
|
|
523
|
+
```
|