d3 playground

This commit is contained in:
James Turk 2024-10-14 01:10:17 -05:00
commit 920e7b98d0
4 changed files with 20825 additions and 0 deletions

37
ideaweb/graph.mjs Normal file
View File

@ -0,0 +1,37 @@
export default class Graph {
constructor() {
this.Default = 0x01;
this.KindCategory = 0x02;
this.KindProject = 0x04;
this.InboxId = 1;
this.nodes = [
{ id: this.InboxId, name: "INBOX", kind: this.KindCategory },
{ id: 2000, name: "UChicago", kind: this.KindCategory },
{ id: 2100, name: "51042", kind: this.KindProject },
{ id: 2400, name: "30239", kind: this.KindProject },
{ id: 2410, name: "D3", kind: this.Default },
{ id: 2420, name: "Altair", kind: this.Default },
];
this.links = [
{ source: 2000, target: 2100 },
{ source: 2000, target: 2400 },
{ source: 2400, target: 2410 },
{ source: 2400, target: 2420 },
];
}
insert(name, kind = "default") {
// todo: fix id
let id = Math.floor(Math.random() * 20000000000);
this.nodes.push({
id: id,
name,
kind: "default",
});
return id;
}
addLink(source, target) {
this.links.push({ source, target });
}
}

116
ideaweb/index.html Normal file
View File

@ -0,0 +1,116 @@
<!doctype html>
<html>
<body>
<div id="container"></div>
<script src="../js/d3.v7.js"></script>
<script type="module">
import Graph from "./graph.mjs";
import ModalEditor from "./modal.mjs";
const graph = new Graph();
const editor = new ModalEditor(graph);
const width = 800;
const height = 800;
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-width / 2, -height / 2, width, height])
.attr("style", "max-width: 100%; height: auto;");
const color = d3.scaleOrdinal(d3.schemeCategory10);
const simulation = d3
.forceSimulation(graph.nodes)
.force(
"link",
d3.forceLink(graph.links).id((d) => d.id),
)
.force("charge", d3.forceManyBody())
.force("x", d3.forceX())
.force("y", d3.forceY());
const selectionGroup = svg.append("g");
const nodeGroup = svg.append("g");
const linkGroup = svg
.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6);
const selection = selectionGroup
.append("circle")
.style("fill", "#ccccccbb")
.style("stroke", "#718e51")
.style("stroke-width", 1)
.attr("r", 10);
let selectionId = 1;
function updateSelection() {
for (let n of graph.nodes) {
if (n.id == selectionId) {
selection.attr("cx", n.x).attr("cy", n.y);
break;
}
}
}
function graphLayout() {
const link = linkGroup
.selectAll("line")
.data(graph.links, (d) => `${d.source},${d.target}`)
.join("line");
const node = nodeGroup
.selectAll("g")
.data(graph.nodes, (d) => d.id)
.join(function (enter) {
const lg = enter.append("g");
lg.append("circle")
.attr("r", 5)
.attr("stroke-width", 1.5)
.attr("fill", (d) => color(d.kind));
lg.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.style("font", "10px monospace")
.text((d) => d.name);
return lg;
})
.attr("transform", (d) => `translate(${d.x}, ${d.y})`);
simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links);
simulation.alpha(1).restart();
}
graphLayout();
const commandBar = svg
.append("g")
.append("text")
.attr("transform", `translate(50, 50)`)
.attr("transform", `translate(${-width / 2 + 10}, ${height / 2})`)
.style("font", "10px monospace")
.text("command bar here")
.style("fill", "darkgreen");
// update the node positions on each tick
simulation.on("tick", () => {
linkGroup
.selectAll("line")
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
nodeGroup
.selectAll("g")
.attr("transform", (d) => `translate(${d.x}, ${d.y})`);
updateSelection();
});
d3.select("body").on("keyup", function (e) {
editor.handleKeyup(e);
commandBar.text(editor.display());
graphLayout();
});
container.append(svg.node());
</script>
</body>
</html>

47
ideaweb/modal.mjs Normal file
View File

@ -0,0 +1,47 @@
export default class ModalEditor {
constructor(graph) {
this.graph = graph;
this.mode = "command";
this.word = "";
}
handleKeyup(event) {
console.log(event);
switch (this.mode) {
case "command":
this.commandModeKey(event);
break;
case "insert":
this.insertModeKey(event);
break;
}
}
commandModeKey(event) {
switch (event.key) {
case "i":
this.mode = "insert";
break;
}
}
insertModeKey(event) {
if (event.key === "Enter") {
let newId = this.graph.insert(this.word, "unknown");
this.graph.addLink(newId, this.graph.InboxId);
this.word = "";
this.mode = "command";
} else {
this.word += event.key;
}
}
display() {
switch (this.mode) {
case "insert":
return "insert> " + this.word;
case "command":
return "(i)nsert";
}
}
}

20625
js/d3.v7.js vendored Normal file

File diff suppressed because it is too large Load Diff