Closed jjackevans closed 1 year ago
Hi @jjackevans, I implemented the following example as a tryout d3 force layout.
<script setup lang="ts">
import { reactive, ref, watch } from "vue";
import * as vNG from "v-network-graph";
import { ForceLayout } from "v-network-graph/lib/force-layout";
const NODE_COUNT = 20
const nodeCount = ref(NODE_COUNT);
const nodes = reactive<vNG.Nodes>({});
const edges = reactive<vNG.Edges>({});
// ref: https://dash14.github.io/v-network-graph/examples/layout.html#position-nodes-with-d3-force
// initialize network
buildNetwork(nodeCount.value, nodes, edges);
watch(nodeCount, () => {
buildNetwork(nodeCount.value, nodes, edges);
});
const configs = reactive(
vNG.defineConfigs({
view: {
layoutHandler: new ForceLayout({
positionFixedByDrag: false,
positionFixedByClickWithAltKey: true,
}),
},
node: {
label: {
visible: false,
},
},
})
);
function buildNetwork(count: number, nodes: vNG.Nodes, edges: vNG.Edges) {
const idNums = [...Array(count)].map((_, i) => i);
// nodes
const newNodes = Object.fromEntries(idNums.map((id) => [`node${id}`, {}]));
Object.keys(nodes).forEach((id) => delete nodes[id]);
Object.assign(nodes, newNodes);
// edges
const makeEdgeEntry = (id1: number, id2: number) => {
return [
`edge${id1}-${id2}`,
{ source: `node${id1}`, target: `node${id2}` },
];
};
const newEdges = Object.fromEntries([
...idNums
.map((n) => [n, (Math.floor(n / 5) * 5) % count])
.map(([n, m]) => (n === m ? [n, (n + 5) % count] : [n, m]))
.map(([n, m]) => makeEdgeEntry(n, m)),
]);
Object.keys(edges).forEach((id) => delete edges[id]);
Object.assign(edges, newEdges);
}
// Add edges between randomly selected nodes
function addEdge() {
let i = Math.floor(Math.random() * NODE_COUNT);
let j = Math.floor(Math.random() * NODE_COUNT);
do {
i = Math.floor(Math.random() * NODE_COUNT);
j = Math.floor(Math.random() * NODE_COUNT);
} while (i == j || `edge${i}-${j}` in edges || `edge${j}-${i}` in edges)
edges[`edge${i}-${j}`] = { source: `node${i}`, target: `node${j}` };
}
</script>
<template>
<div>
<button @click="addEdge">Add an edge</button>
</div>
<v-network-graph
:nodes="nodes"
:edges="edges"
:configs="configs"
/>
</template>
When clicking Add an edge
, the edge is added and the force layout also seems to be reacting and recalculating.
Is this what you would like to achieve?
If not, please show a minimum sample code and I may be able to reply with a more specific answer.
Since some time has elapsed, I close this issue for now. If there are additional questions, please reopen this issue.
Hi there @dash14 ! I have a similar question.
I'm using a force layout and have saved a graph layout in the backend. When the user returns to the graph, I want to display it exactly as they left it, so they can continue their work from where they left off. However, when I try to do this, the simulation creates a new layout.
I assume this happens because I'm adding each node and layout successively.
So, my basic question is: how can I initialize a graph layout with a stored "steady-state" layout, without running the simulation again?
Thank you in advance!
Hi,
I have a graph using D3 to create a layout. When the edges change, I would like the entire graph to re-render the layout. Currently the layout does not adjust when the underlying data does.
Could you suggest how I might achieve that?
Thanks!