Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-loading D3 Graph #88

Closed
jjackevans opened this issue Sep 18, 2022 · 3 comments
Closed

Re-loading D3 Graph #88

jjackevans opened this issue Sep 18, 2022 · 3 comments

Comments

@jjackevans
Copy link

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!

@dash14
Copy link
Owner

dash14 commented Sep 20, 2022

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.

@dash14
Copy link
Owner

dash14 commented Oct 22, 2022

Since some time has elapsed, I close this issue for now.
If there are additional questions, please reopen this issue.

@dash14 dash14 closed this as completed Oct 22, 2022
@piliadis
Copy link

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants