Public
Edited
Nov 7, 2022
Fork of Simple D3
Insert cell
Insert cell
width = 400;

Insert cell
height = 400;
Insert cell
chart = {
const simulation = d3.forceSimulation(data.nodes)
.force("link", d3.forceLink(data.links).id((d) => { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width/2, height/2));

const svg = d3.select("body").append("svg")
.attr("width", width)
.attr("heght", height);
// .attr('viewbox', [0, 0, width, height]);
const nodes = svg.append('g')
.attr("width", width)
.attr("height", height)
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll("circle")
.data(data.nodes)
.join("circle")
.attr("r", 10)
.attr("fill", color)
.call(drag(simulation));
nodes.append("title")
.text(d => d.id);
const links = svg.append('g')
.attr("width", width)
.attr("height", height)
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(data.links)
.join("line")
.attr("length", 50)
.attr("stroke-width", 1);
simulation.on("tick", () => {
links
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
nodes
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});

if (invalidation != null) invalidation.then(() => simulation.stop());
return svg.node();
}
Insert cell
color = (d) => {
return d.sensei === 1 ? 'red' : 'blue';
}
Insert cell
drag = (simulation) => {
const dragStart = (d) => {
if (!d.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}

const dragUpdate = (d) => {
d.fx = d.x;
d.fy = d.y;
}

const dragEnd = (d) => {
if (!d.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}

return d3.drag()
.on("start", dragStart)
.on("drag", dragUpdate)
.on("end", dragEnd);
}
Insert cell
data = ({
nodes: [
{ id: 1, sensei: 1 },
{ id: 2, sensei: 1 },
{ id: 3, sensei: 1 },
{ id: 4, sensei: 1 },
{ id: 5, sensei: 1 },
{ id: 6, sensei: 1 },
{ id: 7, sensei: 1 },
{ id: 8, sensei: 1 },
{ id: 9, sensei: 1 },
{ id: 10, sensei: 2 },
{ id: 11, sensei: 1 },
{ id: 12, sensei: 1 },
{ id: 13, sensei: 1 },
{ id: 14, sensei: 1 },
{ id: 15, sensei: 2 },
{ id: 16, sensei: 2 },
{ id: 17, sensei: 1 },
{ id: 18, sensei: 1 },
{ id: 19, sensei: 2 },
{ id: 20, sensei: 1 },
{ id: 21, sensei: 2 },
{ id: 22, sensei: 1 },
{ id: 23, sensei: 2 },
{ id: 24, sensei: 2 },
{ id: 25, sensei: 2 },
{ id: 26, sensei: 2 },
{ id: 27, sensei: 2 },
{ id: 28, sensei: 2 },
{ id: 29, sensei: 2 },
{ id: 30, sensei: 2 },
{ id: 31, sensei: 2 },
{ id: 32, sensei: 2 },
{ id: 33, sensei: 2 },
{ id: 34, sensei: 2 }
],
links: [
{ source: 2, target: 1 },
{ source: 3, target: 1 }, { source: 3, target: 2 },
{ source: 4, target: 1 }, { source: 4, target: 2 }, { source: 4, target: 3 },
{ source: 5, target: 1 },
{ source: 6, target: 1 },
{ source: 7, target: 1 }, { source: 7, target: 5 }, { source: 7, target: 6 },
{ source: 8, target: 1 }, { source: 8, target: 2 }, { source: 8, target: 3 }, { source: 8, target: 4 },
{ source: 9, target: 1 }, { source: 9, target: 3 },
{ source: 10, target: 3 },
{ source: 11, target: 1 }, { source: 11, target: 5 }, { source: 11, target: 6 },
{ source: 12, target: 1 },
{ source: 13, target: 1 }, { source: 13, target: 4 },
{ source: 14, target: 1 }, { source: 14, target: 2 }, { source: 14, target: 3 }, { source: 14, target: 4 },
{ source: 17, target: 6 }, { source: 17, target: 7 },
{ source: 18, target: 1 }, { source: 18, target: 2 },
{ source: 20, target: 1 }, { source: 20, target: 2 },
{ source: 22, target: 1 }, { source: 22, target: 2 },
{ source: 26, target: 24 }, { source: 26, target: 25 },
{ source: 28, target: 3 }, { source: 28, target: 24 }, { source: 28, target: 25 },
{ source: 29, target: 3 },
{ source: 30, target: 24 }, { source: 30, target: 27 },
{ source: 31, target: 2 }, { source: 31, target: 9 },
{ source: 32, target: 1 }, { source: 32, target: 25 }, { source: 32, target: 26 }, { source: 32, target: 29 },
{ source: 33, target: 3 }, { source: 33, target: 9 }, { source: 33, target: 15 }, { source: 33, target: 16 }, { source: 33, target: 19 }, { source: 33, target: 21 }, { source: 33, target: 23 }, { source: 33, target: 24 }, { source: 33, target: 30 }, { source: 33, target: 31 }, { source: 33, target: 32 },
{ source: 34, target: 9 }, { source: 34, target: 10 }, { source: 34, target: 14 }, { source: 34, target: 15 }, { source: 34, target: 16 }, { source: 34, target: 19 }, { source: 34, target: 20 }, { source: 34, target: 21 }, { source: 34, target: 23 }, { source: 34, target: 24 }, { source: 34, target: 27 }, { source: 34, target: 28 }, { source: 34, target: 29 }, { source: 34, target: 30 }, { source: 34, target: 31 }, { source: 34, target: 32 }, { source: 34, target: 33 }
]
});
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