{
const svg = d3.select(DOM.svg(width, height));
const chart = svg.append('g')
.attr("transform", `translate(${width / 2} ${height / 2})`)
.attr("font-family", "sans-serif");
const size = Math.min(width, height) / 2;
const yOffset = (size - Math.sin(30 * Math.PI / 180) * size) / 2;
const [A, B, C] = [150, 30, -90].map(d => [
Math.cos(d * Math.PI / 180) * size,
Math.sin(d * Math.PI / 180) * size + yOffset
]);
const a = line(B, C);
const b = line(C, A);
const c = line(A, B);
const labelOffset = 80;
const [_A, _B, _C] = [150, 30, -90].map(d => [
Math.cos(d * Math.PI / 180) * (size + labelOffset),
Math.sin(d * Math.PI / 180) * (size + labelOffset) + yOffset
]);
const _a = line(_B, _C);
const _b = line(_C, _A);
const _c = line(_A, _B);
const ticks = d3.range(0, 100, 20).concat(100)
const grid = d3.range(0, 1, 0.1);
chart.append("path")
.attr("d", `M${A}L${B}L${C}Z`)
.attr("fill", "#ececec")
.attr("stroke", "none");
chart.append("g")
.selectAll(".grid")
.data([
grid.map(tick => [a(tick), b(1 - tick)]),
grid.map(tick => [b(tick), c(1 - tick)]),
grid.map(tick => [c(tick), a(1 - tick)])
])
.enter().append("g")
.selectAll(".gridlines")
.data(d => d)
.enter().append("line")
.attr("x1", d => d[0][0])
.attr("y1", d => d[0][1])
.attr("x2", d => d[1][0])
.attr("y2", d => d[1][1])
.attr("stroke", "#fff")
.attr("stroke-width", (d, i) => i & 1 ? 1 : 2);
chart.append("g")
.attr("font-size", 10)
.selectAll(".axis")
.data([
ticks.map(tick => ({ tick, pos: a(tick / 100), rot: 0, anchor: "start"})),
ticks.map(tick => ({ tick, pos: b(tick / 100), rot: 60, anchor: "end"})),
ticks.map(tick => ({ tick, pos: c(tick / 100), rot: -60, anchor: "end"}))
])
.enter().append("g")
.selectAll(".ticks")
.data(d => d)
.enter().append("text")
.attr("transform", d => `translate(${d.pos}) rotate(${d.rot})`)
.attr("text-anchor", d => d.anchor)
.attr("dx", d => 10 * (d.anchor === "start" ? 1 : -1))
.attr("dy", ".3em")
.text(d => d.tick);
chart.append("g")
.attr("font-size", 16)
.selectAll(".labels")
.data([
{ label: "Service", pos: _a(0.5), rot: 60 },
{ label: "Agriculture", pos: _b(0.5), rot: -60 },
{ label: "Industry", pos: _c(0.5), rot: 0 }
])
.enter().append("text")
.attr("transform", d => `translate(${d.pos}) rotate(${d.rot})`)
.attr("text-anchor", "middle")
.text(d => d.label)
chart.selectAll(".countries")
.data(data.map(d => ({
country: d.country,
color: d3.schemeSet3[regions.findIndex(r => r === d.region)],
pos: [
A[0] * d.agriculture / 100 + B[0] * d.industry / 100 + C[0] * d.service / 100,
A[1] * d.agriculture / 100 + B[1] * d.industry / 100 + C[1] * d.service / 100
]
})))
.enter().append("circle")
.attr("r", 5)
.attr("cx", d => d.pos[0])
.attr("cy", d => d.pos[1])
.attr("fill", d => d.color)
.attr("stroke", "#ddd")
.append("title").text(d => d.country);
return svg.node();
}