Published
Edited
Dec 9, 2020
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
types = d3.set(data.nodes, d => d.gene_name);
Insert cell
Insert cell
vis = {
// wait until this cell is visible
await visibility();
const links = data.links.map(d => Object.create(d));
const nodes = data.nodes.map(d => Object.create(d));
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id))
.force("charge", d3.forceManyBody().strength(-30))
.force('collide', d3.forceCollide((180/data.nodes.length)+10)) // this value determines how
.force("x", d3.forceX())
.force("y", d3.forceY());
const svg = d3.select(DOM.svg(1000, 880));
svg.attr("viewBox", [-width / 2, -height / 2, width, height]);
// data layer to keep circles
const g = svg.append("g").attr("id", "circles")
const node = g.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("r", r)
.attr("fill", color)
.call(drag(simulation));
//links
const link = svg.append("g")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(links)
.enter()
.append("line")
.attr("stroke", lineColor)
.attr("stroke-width", d => Math.sqrt(5));
// annotation layer for labels
svg.append("g").attr("id", "annotation");
// another annotation layer for details
svg.append("g").attr("id", "testdetail");

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);
});

invalidation.then(() => simulation.stop());
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
highlight = {
const svg = d3.select(vis);
// used to test out interactivity in this cell
const status = html`<code>highlight: none</code>`;
// event.namespace allows us to add multiple functions for one event
// only needed in examples like this where some events trigger multiple functions
circles.on("mouseover.highlight", function(d) {
d3.select(this)
.raise() // bring to front
.style("stroke", "red")
.style("stroke-width", 1.5);
// show what we interacted with
d3.select(status).text("highlight: " + d.id);
});

circles.on("mouseout.highlight", function(d) {
d3.select(this).style("stroke", null);
d3.select(status).text("highlight: none");
});
return status;
}
Insert cell
Insert cell
hover1 = {
const svg = d3.select(vis);
// used to test out interactivity in this cell
const status = html`<code>hover: none</code>`;

circles.on("mouseover.hover1", function(d) {
let me = d3.select(this);
annotations.insert("text")
.attr("id", "label")
.attr("x", me.attr("cx"))
.attr("y", me.attr("cy"))
.attr("dy", r + 14)
.attr("text-anchor", "middle")
.text(d.name);

// show what we interacted with
d3.select(status).text("hover: " + d.name);
});

circles.on("mouseout.hover1", function(d) {
annotations.select("text#label").remove();
d3.select(status).text("hover: none");
});
return status;
}
Insert cell
Insert cell
hover2 = {
const svg = d3.select(vis);
// used to test out interactivity in this cell
const status = html`<code>hover: none</code>`;

circles.on("mouseover.hover2", function(d) {
let me = d3.select(this);
let div = d3.select("body").append("div");
div.attr("id", "details");
div.attr("class", "tooltip");
let rows = div.append("table")
.selectAll("tr")
.data(Object.keys(Object.getPrototypeOf(d)))
.enter()
.append("tr");
rows.append("th").text(key => key);
rows.append("td").text(key => d[key]);
// show what we interacted with
d3.select(status).text("hover: " + d.id);
return div;
});

circles.on("mousemove.hover2", function(d) {
let div = d3.select("div#details");
// get height of tooltip
let bbox = div.node().getBoundingClientRect();
div.style("left", d3.event.clientX + "px")
div.style("top", (d3.event.clientY - bbox.height) + "px");
});
circles.on("mouseout.hover2", function(d) {
d3.selectAll("div#details").remove();
d3.select(status).text("hover: none");
});
return status;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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