Published
Edited
Mar 19, 2021
5 forks
2 stars
Insert cell
Insert cell
chart = {
const root = tree(data);

const svg = d3.select(DOM.svg(width, height))
.style("width", "100%")
.style("height", "auto")
.style("padding", "8px")
.style("box-sizing", "border-box")
.style("font", "10px sans-serif")
const g = svg.append("g")
const link = g.append("g")
.attr("fill", "none")
.attr("stroke-opacity", 0.2)
.attr("stroke-width", 2)
.selectAll("path")
.data(root.links())
.enter().append("path")
.attr("d", d3.linkRadial()
.angle(d => d.x)
.radius(d => d.y - 3))
.attr("stroke", d => { while (d.source.depth > 1) d.source = d.source.parent; return color(d.source.data.name); })
//.attr("stroke", d => d.depth = 1 ? color(d.target.data.name): d.source = d.source.parent; return color(d.source.data.name))

const node = g.append("g")
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.selectAll("g")
.data(root.descendants().reverse())
.enter().append("g")
.attr("transform", d => `
rotate(${d.x * 180 / Math.PI - 90})
translate(${d.y},0)
`);
const myScale = d3.scaleLinear()
.domain([d3.min(root.leaves().map(leaf => leaf.data.value)), d3.max(root.leaves().map(leaf => leaf.data.value))])
.range([0.2, 1]);
node.append("circle")
//.attr("stroke", d => d.children ? "#34C97C" : "#161616")
.attr("fill", d => { while (d.depth > 1) d = d.parent; return color(d.data.name); })
.attr("stroke", d => { while (d.depth > 1) d = d.parent; return color(d.data.name); })
.attr("stroke-width", 0.75)
.attr("fill-opacity", d => d.children ? 1 : myScale(d.value))
/* .attr("fill-opacity", d => {
let min = d3.min(root.leaves().map(leaf => leaf.data.value))
let max = d3.max(root.leaves().map(leaf => leaf.data.value))
return (d.value-min)/(max-min)})
.attr("stroke-width", d=> d.children ? 2 : 2)*/
.attr("r", d => d.children ? 5:3)
.on("mouseover", function(d, data) {
tooltip
.html("Value: " + data.value + "<br/>" + "Name: " + name(data))
//.html(data.value + "<br/>" + name(data))
.style('visibility', 'visible');
}).on('mousemove', function (d) {
tooltip
.style('top', d.clientY + 10 + 'px')
.style('left', d.clientX + 20 + 'px')
.style("display", "inline-block");
})
.on('mouseout', function () {
tooltip.html(``).style('visibility', 'hidden');
});
node.append("text")
.attr("dy", "0.31em")
.attr("x", d => d.x < Math.PI === !d.children ? 10 : -10)
.attr("text-anchor", d => d.x < Math.PI === !d.children ? "start" : "end")
.attr("transform", d => d.x >= Math.PI ? "rotate(180)" : null)
.attr("transform", d => d.x >= Math.PI ? "rotate(180)" : (d.parent ? null:"rotate(-90)"))
.attr("y", d => d.parent ? 0 : - 10)
.style("font", d => d.children ? "12px sans-serif": "12px sans-serif")
.style("text-transform", d => d.children ? "uppercase": null)
.style("font-weight", d => d.children ? "bold": "normal")
.attr("fill", d => d.children ? "#161616": "#161616")
.text(d => d.data.name)
.filter(d => d.children)
.clone(true).lower()
.attr("stroke", "white")
.attr("stroke-width", 4);
document.body.appendChild(svg.node());

const box = g.node().getBBox();

svg.remove()
.attr("width", box.width)
.attr("height", box.height)
.attr("viewBox", `${box.x} ${box.y} ${box.width} ${box.height}`);
svg.call(d3.zoom()
.extent([[0, 0], [width, height]])
.scaleExtent([1, 8])
.on("zoom", zoomed));

function zoomed({transform}) {
g.attr("transform", transform);
}

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
width = 2000
Insert cell
height = 1000
Insert cell
radius = width / 2
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more