Non-Ribbon Chord Diagram
A chord diagram with thin lines instead of wide ribbons: it shows which nodes are connected rather than how much flows between them. Dots travel back and forth along each line.
About this chart
When lines beat ribbons
Ribbons are good at showing size, but they cover each other when there are many. Thin lines keep every connection in view, so the shape of the network comes through: who links to many, and who to few.
Good for
- Networks where the links matter more than their size
- Dependencies between modules or services
- Small social networks
Think twice when
- When the amounts matter: use ribbons
- Hundreds of links: try a force-directed network
- Readers who need to follow one line across the circle
For developers
Get the code.
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.
For projects that use npm:
How it reads:
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.How it reads:
"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://docs.amcharts.com/v5/getting-started/#root-element
var root = am5.Root.new("chartdiv");
// Set themes
// https://docs.amcharts.com/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
// Create series
// https://docs.amcharts.com/v5/charts/flow-charts/
// a chart whose contents can be zoomed and panned
var chart = root.container.children.push(am5.SerialChartContainer.new(root, {}));
// a chord diagram with thin links instead of ribbons
var series = chart.series.push(am5flow.ChordNonRibbon.new(root, {
sourceIdField: "from",
targetIdField: "to",
valueField: "value"
}));
series.nodes.get("colors").set("step", 2); // every second theme color for the nodes
// a dot on each link runs back and forth between its two nodes, each at its own speed
series.bullets.push(function (_root, _series, dataItem) {
var bullet = am5.Bullet.new(root, {
locationY: Math.random(), // each dot starts somewhere along its link
sprite: am5.Circle.new(root, {
radius: 5, // 5px radius
fill: dataItem.get("source").get("fill") // in the color of the link's source node
})
});
bullet.animate({
key: "locationY", // moves along the link...
to: 1, // ...to the target end...
from: 0, // ...from the source end...
duration: Math.random() * 1000 + 2000, // ...in 2 to 3 seconds...
loops: Infinity, // ...forever...
easing: am5.ease.yoyo(am5.ease.cubic) // ...there and back, slowing at each end
});
return bullet;
});
// straight (not curved) names in the background color, set on the node circles
series.nodes.labels.template.setAll({
textType: "regular",
fill: root.interfaceColors.get("background"),
fontSize: "1.1em", // a little larger than normal text
radius: -5 // pulled 5px in, onto the node circles
});
// a big circle on each node, in the node's color
series.nodes.bullets.push(function (_root, _series, dataItem) {
return am5.Bullet.new(root, {
sprite: am5.Circle.new(root, {
radius: 20, // 20px radius
fill: dataItem.get("fill") // the node's color
})
});
});
// move the bullets container to the back, behind the links and nodes
series.children.moveValue(series.bulletsContainer, 0);
// Set data
// https://docs.amcharts.com/v5/charts/flow-charts/#setting-data
series.data.setAll([
{ from: "A", to: "D", value: 10 },
{ from: "B", to: "D", value: 8 },
{ from: "B", to: "E", value: 4 },
{ from: "B", to: "C", value: 2 },
{ from: "C", to: "E", value: 14 },
{ from: "E", to: "D", value: 8 },
{ from: "C", to: "A", value: 4 },
{ from: "G", to: "A", value: 7 }
]);
// Make stuff animate on load
series.appear(1000, 100);
{
"type": "SerialChartContainer",
"properties": {
"series": [
"#series-0"
]
},
"refs": [
{
"data-0": [
{
"from": "A",
"to": "D",
"value": 10
},
{
"from": "B",
"to": "D",
"value": 8
},
{
"from": "B",
"to": "E",
"value": 4
},
{
"from": "B",
"to": "C",
"value": 2
},
{
"from": "C",
"to": "E",
"value": 14
},
{
"from": "E",
"to": "D",
"value": 8
},
{
"from": "C",
"to": "A",
"value": 4
},
{
"from": "G",
"to": "A",
"value": 7
}
]
},
{
"series-0": {
"type": "ChordNonRibbon",
"settings": {
"sourceIdField": "from",
"targetIdField": "to",
"valueField": "value"
},
"properties": {
"data": "#data-0",
"nodes": {
"properties": {
"labels": {
"properties": {
"template": {
"settings": {
"textType": "regular",
"fill": "@root.interfaceColors.get('background')",
"fontSize": "1.1em",
"radius": -5
}
}
}
},
"bullets": [
{
"type": "Bullet",
"settings": {
"sprite": {
"type": "Circle",
"settings": {
"radius": 20,
"fill": "@root.interfaceColors.get('primaryButton')"
}
}
}
}
]
},
"settings": {
"colors": {
"type": "ColorSet",
"settings": {
"step": 2
}
}
}
},
"bullets": [
{
"type": "Bullet",
"settings": {
"sprite": {
"type": "Circle",
"settings": {
"radius": 5,
"fill": "@root.interfaceColors.get('primaryButton')"
}
},
"animations": [
{
"key": "locationY",
"from": 0,
"to": 1,
"duration": 1234.9315250866266,
"loops": 0,
"easing": "cubic",
"yoyo": true
}
]
}
}
]
}
}
}
]
}



