titleChart = {
const radius = 7
const highlightColor = "pink"
const zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", zoomed)
const simulation = d3.forceSimulation(networkData.nodes)
.force("link", d3.forceLink(networkData.links).id(d => d.id))
.force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2))
.on("tick", ticked)
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto;")
const g = svg.append("g")
const link = g.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll()
.data(networkData.links)
.join("line")
.attr("stroke-width", d => Math.sqrt(d.value))
const node = g.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll()
.data(networkData.nodes)
.join("circle")
.attr("r", radius)
.attr("fill", d => color(d.group))
.attr("class", "nodes")
const label = g.append("text")
node
.on("mouseover", function(e,d){
d3.select(this)
.transition()
.duration(200)
.attr("fill", highlightColor)
.attr("r", radius*2)
.attr("stroke", "white")
.attr("stroke-width", radius/2)
console.log(d)
const labelText = `${d.label}`
label
.attr("display", null)
.attr("font-size", 15)
.attr("transform", `translate(${d3.select(this).attr("cx")},${d3.select(this).attr("cy")})`)
.attr("dx", +14)
.attr("dy", -10)
.text(d => labelText)
})
.on("mouseleave", function(e, d){
d3.selectAll(".nodes")
.transition()
.duration(200)
.attr("fill", d => color(d.group))
.attr("r", radius)
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
label
.attr("display", "none")
})
// Add a drag behavior.
node.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
svg.call(zoom)
// Set the position attributes of links and nodes each time the simulation ticks.
function ticked() {
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);
}
// Reheat the simulation when drag starts, and fix the subject position.
function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
// Update the subject (dragged node) position during drag.
function dragged(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
// Restore the target alpha so the simulation cools after dragging ends.
// Unfix the subject position now that it’s no longer being dragged.
function dragended(event) {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}
function zoomed(event){
const {transform} = event
g.attr("transform", transform)
g.attr("stroke-width", 1/transform.k)
}
// When this cell is re-run, stop the previous simulation. (This doesn’t
// really matter since the target alpha is zero and the simulation will
// stop naturally, but it’s a good practice.)
invalidation.then(() => simulation.stop());
// Add a title
const title = svg.append("g")
.append("text")
.attr("x", width / 2)
.attr("y", (margins.top / 2))
.attr("text-anchor", "middle")
.attr("front-weight", "bold")
.attr("font-family", "Helvetica Neue, Arial")
.attr("font-size", "20px")
.text("Some ridiculous network data visualization")
return Object.assign(svg.node(), {scales: {color}})
}