Public
Edited
Feb 27, 2024
Insert cell
Insert cell
viewof vis = {
let d3cola = cola.d3adaptor(d3).convergenceThreshold(0.1);

const width = 960,
height = 700,
margin = 20,
pad = 12;

let outer = d3.select(DOM.svg(width, height)).attr("pointer-events", "all");

outer
.append("rect")
.attr("class", "background")
.attr("width", "100%")
.attr("height", "100%")
.append("svg:defs")
.append("svg:marker")
.attr("id", "end-arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 8)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5L2,0")
.attr("stroke-width", "0px")
.attr("fill", "#000");

let vis = outer
.append("g")
.attr("transform", "translate(250,250) scale(0.3)");

let { nodes, edges } = JSON.parse(JSON.stringify(data));

d3cola
.avoidOverlaps(true)
.convergenceThreshold(1e-3)
.flowLayout("x", 150)
.size([width, height])
.nodes(nodes)
.links(edges)
.jaccardLinkLengths(150);

let link = vis
.selectAll(".link")
.data(edges)
.enter()
.append("path")
.attr("class", "link");

let node = vis
.selectAll(".node")
.data(nodes)
.enter()
.append("rect")
.classed("node", true)
.attr("rx", 5)
.attr("ry", 5)
.call(d3cola.drag);

let label = vis
.selectAll(".label")
.data(nodes)
.enter()
.append("text")
.attr("class", "label")
.text(function (d) {
return d.name;
})
.call(d3cola.drag)
.each(function (d) {
var b = getBBox(this);
var extra = 2 * margin + 2 * pad;
d.width = b.width + extra;
d.height = b.height + extra;
});
d3cola
.start(50, 100, 200)

.on("tick", function () {
node
.each(function (d) {
d.innerBounds = d.bounds.inflate(-margin);
})
.attr("x", function (d) {
return d.innerBounds.x;
})
.attr("y", function (d) {
return d.innerBounds.y;
})
.attr("width", function (d) {
return d.innerBounds.X - d.innerBounds.x;
})
.attr("height", function (d) {
return d.innerBounds.height();
});

link.attr("d", function (d) {
var route = cola.makeEdgeBetween(
d.source.innerBounds,
d.target.innerBounds,
5
);
return lineFunction([route.sourceIntersection, route.arrowStart]);
});

label
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y + (margin + pad) / 2;
});
})
.on("end", routeEdges(d3cola, link));

outer.node().value = { nodes, edges };

return outer.node();
}
Insert cell
import { autoBBox } from "@rlesser/automatic-getbbox@344"
Insert cell
Insert cell
Insert cell
Insert cell
graphlibDot = require("https://bundle.run/graphlib-dot@0.6.4")
Insert cell
Insert cell
routeEdges = function (d3cola, link) {
return function () {
d3cola.prepareEdgeRouting();
link.attr("d", function (d) {
return lineFunction(d3cola.routeEdge(d));
});
};
}
Insert cell
lineFunction = d3
.line()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
Insert cell
vis
Insert cell
Insert cell
getBBox = (element) => {
const svg = html`<svg style="border:solid 1px red;">
<g name="content">
${element.outerHTML}
</g>
</svg>`;

// Add the SVG element to the DOM so we can determine its size.
document.body.appendChild(svg);

// Computing the bounding box of the content.
const box = svg.querySelector("[name=content]").getBBox();

// Remove the SVG element from the DOM.
svg.remove();

console.log(element.outerHTML);
return box;
}
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