chart = {
const simulation = d3.forceSimulation(data.nodes)
.force('charge', d3.forceManyBody().strength(-300))
.force('link', d3.forceLink(data.links).id(d => d.name).distance(50))
.force('center', d3.forceCenter(250, 100));
const svg = d3.create("svg").attr("viewBox", [0, 0, 500, 200]);
const ageScale = d3.scaleLinear()
.domain(d3.extent(data.nodes, d => d.age))
.range([10, 30]);
const link = svg
.selectAll('path.link')
.data(data.links)
.enter()
.append('path')
.attr('class', 'link')
.attr('fill', 'none');
const node = svg.selectAll('.node')
.data(data.nodes)
.enter()
.append('g')
.attr("class", "node")
.style("text-anchor", "middle")
.attr("class", "nodes");
node.append('circle')
.attr('r', d => ageScale(d.age))
.attr("class", "circle");
node.append('g')
.selectAll('.circle--small')
.data(x => x.shoes)
.enter()
.append('circle')
.attr('r', SMALL_CIRCLE_RADIUS)
.attr('cx', function (d,i) {
const nodeRadius = ageScale(d3.select(this.parentNode).datum().age);
const factor = (i / nodeRadius) * (SMALL_CIRCLE_RADIUS / 2) * 5;
return nodeRadius * Math.cos(factor - Math.PI * 0.5);
})
.attr('cy', function (d,i) {
const nodeRadius = ageScale(d3.select(this.parentNode).datum().age);
const factor = (i / nodeRadius) * (SMALL_CIRCLE_RADIUS / 2) * 5;
return nodeRadius * Math.sin(factor - Math.PI * 0.5);
})
.attr("class", "circle--small");
node.append('text')
.attr("dy", 4)
.attr("dx", 0)
.attr('class', 'label')
.text(d => d.name);
const drag = (simulation) => {
const dragstarted = (event) => {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
const dragged = (event) => {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
const dragended = (event) => {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
};
node.call(drag(simulation));
simulation.on('tick', () => {
node.attr("transform", d => `translate(${d.x},${d.y})`);
link.attr('d', d => d3.line()([
[d.source.x, d.source.y],
[d.target.x, d.target.y]]))
});
return svg.node();
}