Public
Edited
Jun 13, 2024
Insert cell
Insert cell
Insert cell
chart = {
let displayScale = 0.3;
const height = width;
const links = data.links; //.map((d) => Object.create(d));
const nodes = data.nodes; //.map((d) => Object.create(d));

const simulation = d3
.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-30))
.force(
"link",
d3
.forceLink(links)
.strength((d) => (d.source.strength ? d.source.strength : 2))
.distance((d) => (d.distance ? d.distance : 10))
.iterations(10)
)
.force("y", d3.forceY(height).strength(0.01))
.on("tick", ticked);

invalidation.then(() => simulation.stop());

const drag = d3
.drag()
.subject(({ x, y }) =>
simulation.find(
(x - width / 2) / displayScale,
(y - height / 2) / displayScale,
40 / displayScale
)
)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);

const context = DOM.context2d(width, height);

function ticked() {
context.clearRect(0, 0, width, height);

context.save();
context.translate(width / 2, height / 2);
context.scale(displayScale, displayScale);
context.beginPath();
for (const d of links) {
context.moveTo(d.source.x, d.source.y);
context.lineTo(d.target.x, d.target.y);
}
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
for (const d of nodes) {
context.moveTo(d.x + 3, d.y);
context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
}
context.fill();
context.strokeStyle = "#fff";
context.stroke();
context.restore();
}

function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}

function dragged(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}

function dragended(event) {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}

return d3.select(context.canvas).call(drag).node();
}
Insert cell
data.nodes
Insert cell
data.links
Insert cell
data = {
// const n = 20;
let { n, m } = form;
let rnd = d3.randomUniform(1, 20);
const nodes = Array.from({ length: n * m }, (_, i) => ({
index: i
}));
const links = [];

for (let x = 0; x < n; ++x) {
for (let y = 0; y < m; ++y) {
let distance = rnd();
if (y > 0)
links.push({ source: (y - 1) * n + x, target: y * n + x, distance });
if (x > 0)
links.push({ source: y * n + (x - 1), target: y * n + x, distance });
}
}

let height = width;
nodes.slice(0, m).map((d) => {
Object.assign(d, { fx: -width * 1.3, fy: -height });
});

nodes.slice(nodes.length - m, nodes.length).map((d) => {
Object.assign(d, { fx: width * 1.3, fy: -height });
});

// Object.assign(nodes[nodes.length - 1], { fx: width, fy: 0 });

return { nodes, links };
}
Insert cell
width = 800
Insert cell
d3 = require("d3")
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