Trying to recreate a reusable version of this type, without the D3 chord diagram business
https://www.nytimes.com/interactive/2018/06/20/business/economy/immigration-economic-impact.html
The labels are harder to programatically position, so I've opted for coordinates positioned on the link itself, inset from from end.
The chordNetwork function could be called with any set of nodes and links if you wish.
Built with blockbuilder.org
forked from tomshanley's block: Recreating the NY Times immigration flows chart, now with some extra links to make the overlaps look nicer
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="links.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="chordNetwork.js"></script>
<script src="appendArrow.js"></script>
<script src="triangleEquations.js"></script>
<style>
body {
font-family: sans-serif
}
text {
text-anchor: middle
}
path {
fill: none;
stroke-linecap: square;
stroke-opacity: 1
}
</style>
</head>
<body>
<div class="header">
<p>A D3.js re-creation of the New York Times' chart from the June 20 2018 article <a href="https://www.nytimes.com/interactive/2018/06/20/business/economy/immigration-economic-impact.html https://www.nytimes.com/interactive/2018/06/20/business/economy/immigration-economic-impact.html">Migrants Are on the Rise Around the World, and Myths About Them Are Shaping Attitudes"</a>.</p>
<h1>Migration in 2017 in millions</h1>
</div>
<div id="chart"></div>
<div class="footer">
<p>Data source: United Nations Department of Economic and Social Affairs, Population Division, <a href="https://www.un.org/en/development/desa/population/migration/publications/migrationreport/docs/MigrationReport2017.pdf">Migration Report 2017</a>.</p>
</div>
<script>
console.clear();
let nodes = [
{"id": "Europe"},
{"id": "Asia"},
{"id": "Oceania"},
{"id": "Africa"},
{"id": "Latin America"},
{"id": "North America"},
];
let links = migration2017
//Generate dummy data
//let n = 6;
//var s = 0;
//var t = 0;
/*nodes = d3.range(n).map(function(d) {
return { id: d };
});
for (s = 0; s < n; s++) {
target = 0;
for (t = 0; t < n; t++) {
let link = {};
link.source = s;
link.target = t;
link.value = s == t ? Math.random() * 100 : Math.random() * 20;
links.push(link);
}
}*/
let colour = d3
.scaleOrdinal()
.domain(nodes.map(d => d.id)) //.range(['#1b9e77','#d95f02','#7570b3','#e7298a','#66a61e','#e6ab02'])
.range(["#eb978f"]);
const width = 600;
const height = width;
const m = 150;
const margin = { top: m, bottom: m, left: m, right: m };
let strokeWidth = d3.scaleLinear()
.domain(d3.extent(links, d => d.value))
.range([1, 20]);
let chartData = createChordData(nodes, links, width, height);
let svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
let chart = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
let g = chart
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
let paths = g
.selectAll(".link")
.data(chartData.links)
.enter()
.append("g")
paths.append("path")
.attr("d", function(d) {
return d.path;
})
.style("stroke-width", d => (strokeWidth(d.value) + 3))
.style("stroke", "white")
path = paths.append("path")
.attr("d", function(d) {
return d.path;
})
.style("stroke-width", d => strokeWidth(d.value))
.style("stroke", d => colour(d.source))
path.each(appendArrow)
path.each(appendLinkLabel)
let nodeLabels = g
.selectAll(".overlay")
.data(chartData.nodes)
.enter()
.append("g")
.append("text")
.text(d => d.id)
.style("fill", "black")
.attr("x", d => d.labelX)
.attr("y", d => (d.labelY + 6));
function roundValue(n) {
n = Math.round(n * 10)/10
return n
}
function appendLinkLabel(d) {
let thisPath = d3.select(this).node();
let pathLength = thisPath.getTotalLength();
let point = thisPath.getPointAtLength(pathLength - 20);
let parentG = d3.select(this.parentNode)
let label = parentG.append("g")
.attr("transform", "translate(" + point.x + "," + point.y + ")")
label.append("text")
.style("fill", "white")
.style("stroke", "white")
.style("stroke-width", "5px")
label.append("text")
.style("fill", colour(d.source))
.style("stroke", "none")
let text = d.value == 0 ? "" : roundValue(d.value)
label.selectAll("text")
.text(text)
.attr("dy", "0.35em")
}
</script>
</body>
https://d3js.org/d3.v4.min.js