Published
Edited
Apr 5, 2020
2 stars
Insert cell
Insert cell
chart = {
const data = getData(parentIDs)
const SQRT3 = Math.sqrt(3)
const hexagonPoly = [[0,-1],[SQRT3/2,0.5],[0,1],[-SQRT3/2,0.5],[-SQRT3/2,-0.5],[0,-1],[SQRT3/2,-0.5]];
function generateHexagon(hexRadius){
const hexagonPath = "m" + hexagonPoly.map(function(p){ return [p[0]*hexRadius, p[1]*hexRadius].join(','); }).join('l') + "z";
return hexagonPath
}
const svg = d3.create("svg")
//.attr("viewBox", [0, 0, width, height])
.attr('width', 500)
.attr('height', 500)
.style("font", "10px sans-serif")
.style("overflow", "visible")
.attr("text-anchor", "middle");

const node = svg.append("g")
.attr("pointer-events", "all")
.selectAll("g")
.data(data)
.join("g")
.attr("transform", d => `translate(${d.x},${d.y})`);
node.append("path")
.attr("id", d => (d.circleUid = DOM.uid("circle")).id)
.attr("d", d => circle(d.r + 3))
.attr("display", "none")

node.filter(d => d.height === 1).append("circle")
.attr('class', 'nodeWrapper')
.attr("r", d => d.r)
.attr("stroke", "black")
.attr("fill", d => d.children ? "none" : "black")
.attr("pointer-events", d => d.children ? "all" : "none");
node.filter(d => d.height === 0).append("path")
.attr('class', 'hexagon')
.attr("d", d => generateHexagon(d.r+4))
.attr("stroke", "black")
.attr("fill", d => d.children ? "none" : "black")
.attr("pointer-events", d => d.children ? "all" : "none");

node.filter(d => d.height === 1).append("text")
.attr("fill", "black")
.append("textPath")
.attr("xlink:href", d => d.circleUid.href)
.attr("startOffset", "50%")
.attr('font-size', '12px')
.text(d => d.data.id);

node.filter(d => d.height === 0).append("text")
.attr("fill", "#fff")
.attr('font-size', '16px')
.text(d => d.data.id)

return svg.attr("viewBox", autoBox).node();
}
Insert cell
Insert cell
parentIDs = [{key: "1001", values: 1}, {key: "1002", values: 3}, {key: "1003", values: 8}, {key: "1004", values: 15}, {key: "1005", values: 6}]
Insert cell
function getData(parentIDs){
var rawData = []
rawData.push({id: 'root'})
parentIDs.map((d,i)=>{
rawData.push({id: d.key, parentId: 'root', size: d.values})
for (var e = 0; e < d.values; e++) {
rawData.push({id: e.toString(), parentId: d.key, size: 1})
}
})
const vData = d3.stratify()(rawData)
const vLayout = d3.pack().size([width, height]).padding(10)
const vRoot = d3.hierarchy(vData).sum(function (d) { return d.data.size; });
const vNodes = vLayout(vRoot);
const data = vNodes.descendants().slice(1)
return data
}
Insert cell
circle = d3.arc()
.innerRadius(0)
.outerRadius(d => d)
.startAngle(-Math.PI)
.endAngle(Math.PI)
Insert cell
function autoBox() {
document.body.appendChild(this);
const {x, y, width, height} = this.getBBox();
document.body.removeChild(this);
return [x, y, width, height];
}
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