A network graph: nodes joined by lines, laid out by forces that push them apart and pull linked ones together. Here, three separate trees held together by two cross-links.
Real structures are rarely pure trees: one team works with another, one page links to another section. Cross-links add those connections on top of the hierarchy, and the forces pull the linked groups together, so clusters and the bridges between them show up on their own.
Built with amCharts 5, a JavaScript library. The JavaScript includes your theme and renderer (canvas or SVG); the JSON also follows the changes you make with the controls.
npm install @amcharts/amcharts5. See Getting started.
The same chart as a JSON config. Chart Maker reads and writes this format, the library's JSON parser turns it into a chart, and the <am5-chart> element puts it on a page with no code."type" is the class to create and "settings" what you would pass to its new() in code; "properties" fill in its parts, lists such as series and axes or templates such as columns.template; "refs" holds objects used in more than one place ("#series-0" stands for the one named series-0); a string starting with "@" takes a value from another object, such as "@series.get('fill')".
A complete page. Save it as an .html file and open it in a browser.
Paste this into an AI coding assistant to build the chart from scratch. More in amCharts & AI.
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
var data = {
name: "Root",
value: 0,
children: [
{
name: "1",
linkWith: ["2"],
children: [
{
name: "A",
children: [
{ name: "A1", value: 1 },
{ name: "A2", value: 1 },
{ name: "A3", value: 1 },
{ name: "A4", value: 1 },
{ name: "A5", value: 1 }
]
},
{
name: "B",
children: [
{ name: "B1", value: 1 },
{ name: "B2", value: 1 },
{ name: "B3", value: 1 },
{ name: "B4", value: 1 },
{ name: "B5", value: 1 }
]
},
{
name: "C",
children: [
{ name: "C1", value: 1 },
{ name: "C2", value: 1 },
{ name: "C3", value: 1 },
{ name: "C4", value: 1 },
{ name: "C5", value: 1 }
]
}
]
},
{
name: "2",
linkWith: ["3"],
children: [
{
name: "D", value:1
},
{
name: "E", value:1
}
]
},
{
name: "3",
children: [
{
name: "F",
children: [
{ name: "F1", value: 1 },
{ name: "F2", value: 1 },
{ name: "F3", value: 1 },
{ name: "F4", value: 1 },
{ name: "F5", value: 1 }
]
},
{
name: "H",
children: [
{ name: "H1", value: 1 },
{ name: "H2", value: 1 },
{ name: "H3", value: 1 },
{ name: "H4", value: 1 },
{ name: "H5", value: 1 }
]
},
{
name: "G",
children: [
{ name: "G1", value: 1 },
{ name: "G2", value: 1 },
{ name: "G3", value: 1 },
{ name: "G4", value: 1 },
{ name: "G5", value: 1 }
]
}
]
}
]
};
// Create wrapper container
var chart = root.container.children.push(
am5.SerialChartContainer.new(root, {
width: am5.percent(100), // fills the whole chart area
height: am5.percent(100),
layout: root.verticalLayout
})
);
// Create series
// https://www.amcharts.com/docs/v5/charts/hierarchy/#Adding
var series = chart.series.push(
am5hierarchy.ForceDirected.new(root, {
singleBranchOnly: false,
downDepth: 1, // a click opens one more level
// the root node isn't drawn: nodes 1, 2 and 3 are the tops of their own trees
topDepth: 1,
maxRadius: 25, // the biggest circles 25px...
minRadius: 12, // ...the smallest 12px
valueField: "value",
categoryField: "name",
childDataField: "children",
// linkWith in the data lists other nodes by name (the idField) to link to across the trees
idField: "name",
linkWithStrength: 0.3, // how strongly those links pull (the default is 0.5)
linkWithField: "linkWith",
manyBodyStrength: -15, // the circles push each other away...
centerStrength: 0.5 // ...and are pulled toward the middle
})
);
series.get("colors").set("step", 2); // each new color skips one in the palette, for more contrast
// A soft shadow under each circle
series.circles.template.setAll({
shadowColor: am5.color(0x000000),
shadowOpacity: 0.3,
shadowBlur: 6,
shadowOffsetX: 2,
shadowOffsetY: 2
});
series.data.setAll([data]);
series.set("selectedDataItem", series.dataItems[0]); // start with the root selected, so the trees show
// Make stuff animate on load
series.appear(1000, 100);
{
"type": "SerialChartContainer",
"settings": {
"width": {
"type": "Percent",
"value": 100
},
"height": {
"type": "Percent",
"value": 100
},
"layout": {
"type": "VerticalLayout"
}
},
"properties": {
"series": [
"#series-0"
]
},
"refs": [
{
"data-0": [
{
"name": "Root",
"value": 0,
"children": [
{
"name": "1",
"linkWith": [
"2"
],
"children": [
{
"name": "A",
"children": [
{
"name": "A1",
"value": 1
},
{
"name": "A2",
"value": 1
},
{
"name": "A3",
"value": 1
},
{
"name": "A4",
"value": 1
},
{
"name": "A5",
"value": 1
}
],
"__parse": true
},
{
"name": "B",
"children": [
{
"name": "B1",
"value": 1
},
{
"name": "B2",
"value": 1
},
{
"name": "B3",
"value": 1
},
{
"name": "B4",
"value": 1
},
{
"name": "B5",
"value": 1
}
],
"__parse": true
},
{
"name": "C",
"children": [
{
"name": "C1",
"value": 1
},
{
"name": "C2",
"value": 1
},
{
"name": "C3",
"value": 1
},
{
"name": "C4",
"value": 1
},
{
"name": "C5",
"value": 1
}
],
"__parse": true
}
],
"__parse": true
},
{
"name": "2",
"linkWith": [
"3"
],
"children": [
{
"name": "D",
"value": 1
},
{
"name": "E",
"value": 1
}
],
"__parse": true
},
{
"name": "3",
"children": [
{
"name": "F",
"children": [
{
"name": "F1",
"value": 1
},
{
"name": "F2",
"value": 1
},
{
"name": "F3",
"value": 1
},
{
"name": "F4",
"value": 1
},
{
"name": "F5",
"value": 1
}
],
"__parse": true
},
{
"name": "H",
"children": [
{
"name": "H1",
"value": 1
},
{
"name": "H2",
"value": 1
},
{
"name": "H3",
"value": 1
},
{
"name": "H4",
"value": 1
},
{
"name": "H5",
"value": 1
}
],
"__parse": true
},
{
"name": "G",
"children": [
{
"name": "G1",
"value": 1
},
{
"name": "G2",
"value": 1
},
{
"name": "G3",
"value": 1
},
{
"name": "G4",
"value": 1
},
{
"name": "G5",
"value": 1
}
],
"__parse": true
}
],
"__parse": true
}
],
"__parse": true
}
]
},
{
"series-0": {
"type": "ForceDirected",
"settings": {
"singleBranchOnly": false,
"downDepth": 1,
"topDepth": 1,
"maxRadius": 25,
"minRadius": 12,
"valueField": "value",
"categoryField": "name",
"childDataField": "children",
"idField": "name",
"linkWithStrength": 0.3,
"linkWithField": "linkWith",
"manyBodyStrength": -15,
"centerStrength": 0.5,
"selectedDataItem": "@self.dataItems.0",
"colors": {
"type": "ColorSet",
"settings": {
"step": 2,
"passOptions": {
"hue": 0.05,
"saturation": 0,
"lightness": 0
},
"colors": [
{
"type": "Color",
"value": "#67b7dc"
},
{
"type": "Color",
"value": "#6794dc"
},
{
"type": "Color",
"value": "#6771dc"
},
{
"type": "Color",
"value": "#8067dc"
},
{
"type": "Color",
"value": "#a367dc"
}
],
"reuse": false,
"startIndex": 0,
"stateAnimationDuration": 600
}
}
},
"properties": {
"data": "#data-0",
"circles": {
"properties": {
"template": {
"settings": {
"shadowColor": {
"type": "Color",
"value": "#000000"
},
"shadowOpacity": 0.3,
"shadowBlur": 6,
"shadowOffsetX": 2,
"shadowOffsetY": 2
}
}
}
}
}
}
}
]
}