Published
Edited
Jan 12, 2021
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
graph = {
let graph = {
nodes: [],
links: []
};

for (let i = 0; i < numberOfNodes; i++) {
graph.nodes.push({
id: i,
name: i + 1 + "",
width: 60,
height: 40,
visible: true,
relativeX: 0,
relativeY: 5
});

for (let j = i + 1; j < numberOfNodes; j++) {
graph.links.push({ source: i, target: j, visible: true });
}
}
svgs.selectAll(".cleanOnInit").remove();
return graph;
}
Insert cell
svgs = d3.select(visual)
Insert cell
color = d3.scaleOrdinal(d3.schemeCategory10);
Insert cell
nodeGroup = {
let nodeGroup = svgs.selectAll(".draggableNodeGroup")
.data(graph.nodes)
.enter().append("g")
.attr("class", "draggableNodeGroup cleanOnInit")
.style("visibility", function (d) {
return d.visible == true ? "visible" : "hidden";
})
.attr("draggable", true)
.call(d3cola.drag()
.on("start", (d) => {
d.fx = d.x;
d.fy = d.y;
})
.on("drag", (d) => {
d.fx = d3.event.x;
d.fy = d3.event.y;
})
.on("end", (d) => {
d.fx = null;
d.fy = null;
})
);
return nodeGroup;
}
Insert cell
node = {
let node = nodeGroup
.append("circle")
.attr("class", "node cleanOnInit")
.attr("r", 20)
.attr("cx", 0)
.attr("cy", 0)
.attr("stroke-width", "4px")
.attr("stroke", "black")
.style("fill", function (d) { return color(d.id); });

node.append("title")
.text(function (d) { return d.name; });

nodeGroup.append("text")
.attr("class", "label cleanOnInit")
.text(function (d) { return d.name; })
.attr("x", function (d) {
return d.relativeX;
})
.attr("y", function (d) {
var that = this;
return d.relativeY;
});
return node;
}
Insert cell
Insert cell
configuration = new Object(
{
"originX": 0,
"originY": 0,
"dragStartX":0,
"dragStartY": 0,
"width": 30000,//Number.MAX_SAFE_INTEGER,
"height": 30000,//Number.MAX_SAFE_INTEGER
"svgWidth": 600,
"svgHeight": 600
});
Insert cell
d3cola = cola
.d3adaptor(d3)
.linkDistance(240)
.avoidOverlaps(true)
.size([configuration.svgWidth, configuration.svgHeight])
.nodes(graph.nodes)
.links(graph.links)
.on("tick", () => {
updateRender();
})
.start()
Insert cell
svgGroup = {
let svgGroup = svgs.selectAll(".draggableGroup")
.data([{"x": 0, "y": 0}])
.enter()
.append("g")
.attr("class", "draggableGroup" + " cleanOnInit")
// .attr("class", "draggableGroup")
.attr("id", "parentGroup")
.attr("draggable", true)
.lower()
.call(d3.drag()
.on('start', () => {
configuration.dragStartX = d3.event.x;
configuration.dragStartY = d3.event.y;
})
.on("drag", () => {
//apply transforma to graph
transformGroup(d3.event.x - configuration.dragStartX, d3.event.y - configuration.dragStartY);
updateRender();
configuration.dragStartX = d3.event.x;
configuration.dragStartY = d3.event.y;
})
.on("end", () => {
//apply transforma to graph
transformGroup(d3.event.x - configuration.dragStartX, d3.event.y - configuration.dragStartY);
updateRender();
configuration.dragStartX = d3.event.x;
configuration.dragStartY = d3.event.y;
})
);
return svgGroup;
}
Insert cell
rectangle = {
let rectangle = svgGroup
.selectAll(".background")
.data([{"x": 0, "y": 0}])
.enter()
.append("rect")
.attr("x", configuration.originX)
.attr("y", configuration.originY)
.attr("rx", 0)
.attr("ry", 0)
.attr("width", configuration.width)
.attr("height", configuration.height)
.attr("class", "background" + " cleanOnInit")
.style("stroke", "black")
.style("fill", "white")
.lower();
return rectangle;
}
Insert cell
transformGroup = (offsetX, offsetY) => {
console.log("graph.length: "+graph.nodes.length);
for (let node of graph.nodes){
node.x += offsetX;
node.y += offsetY;
}
}
Insert cell
function updateRender(){
let svg = d3.select("#mainSvg");

let nodeGroup = svg.selectAll(".draggableNodeGroup");
let link = svg.selectAll(".link");
let label = svg.selectAll(".label");

//update
nodeGroup.attr("transform", function (d) {
return "translate("+ (d.x) +","+ (d.y)+")";
});

link.attr("x1", function (d) { return (d.source.x); })
.attr("y1", function (d) { return (d.source.y); })
.attr("x2", function (d) { return (d.target.x); })
.attr("y2", function (d) { return (d.target.y); })
.style("visibility", function (d) {
return d.visible == true ? "visible" : "hidden";
});
}
Insert cell
html`<style>
.node {
stroke: #fff;
stroke-width: 1.5px;
cursor: move;
}

.link {
stroke: #999;
stroke-width: 3px;
stroke-opacity: 1;
}

.label {
fill: white;
font-family: Verdana;
font-size: 13px;
text-anchor: middle;
cursor: move;
}

.draggableGroup {
cursor: move;
transition: stroke-width 0.1s ease-out,
fill 0.1s ease-out,
stroke 0.1s ease-out;

stroke: white;
stroke-width: 0.25;
}
</style>
`

Insert cell
d3 = require("d3@5")
Insert cell
cola = require("webcola@3/WebCola/cola.min.js")
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