Public
Edited
Jun 9, 2022
1 fork
4 stars
Insert cell
# Timeline network
Insert cell
svg = {
const links = data.edges;
const nodes = data.nodes;

const simulation = d3
.forceSimulation(nodes)
.force(
"link",
d3
.forceLink(links)
.id((d) => d.id)
.distance(10)
)
.force("charge", d3.forceManyBody())
.force(
"x",
d3.forceX((d) => x(new Date(d.attributes.order)))
)
.force(
"y",
d3.forceY((d) => 400)
);

const svg = d3.create("svg").attr("width", width).attr("height", 800);

svg
.append("defs")
.append("marker")
.attr("id", "arrow")
.attr("viewBox", [0, 0, markerBoxWidth, markerBoxHeight])
.attr("refX", refX)
.attr("refY", refY)
.attr("markerWidth", markerBoxWidth)
.attr("markerHeight", markerBoxHeight)
.attr("orient", "auto")
.append("path")
.attr("d", d3.line()(arrowPoints))
.attr("stroke", "#989C94");

const link = svg
.append("g")
.selectAll("line")
.data(links)
.join("line")
.attr("stroke", "#989C94")
.attr("stroke-opacity", 0.7)
.attr("stroke-width", 1)
.attr("fill", "none")
.attr("marker-end", "url(#arrow)");

const node = svg
.append("g")
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", 4)
.attr("fill-opacity", "0.5")
.attr("stroke", "#555")
.attr("fill", "#555")
.on("click", (event, d) =>
console.log(`Company: ${d.id}, cluster: ${d.attributes.group}`)
);

const labels = svg
.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.text((d) => d.label)
.attr("fill", "#000")
.attr("font-family", "Source Serif Pro")
.attr("font-size", 6)
.attr("text-anchor", "middle");

node.append("title").text((d) => d.id);

simulation.on("tick", () => {
link
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);

node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);

labels.attr("x", (d) => d.x).attr("y", (d) => d.y);
});

svg.append("g").call(xAxis).select(".domain").remove();

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

return svg.node();
}
Insert cell
nodes = data.nodes
Insert cell
markerBoxWidth = 10
Insert cell
markerBoxHeight = 10
Insert cell
refX = markerBoxWidth / 2
Insert cell
refY = markerBoxHeight / 2
Insert cell
arrowPoints = [
[0, 0],
[0, 20],
[20, 10]
]
Insert cell
x.domain()
Insert cell
xAxis = d3.axisBottom(x).ticks(d3.timeYear).tickFormat(d3.timeFormat("%Y"))
Insert cell
x = d3
.scaleTime()
.range([0, width])
.domain(d3.extent(nodes, (d) => new Date(d.attributes.order)))
Insert cell
height = 700
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