dash14 / v-network-graph

An interactive network graph visualization component for Vue 3
https://dash14.github.io/v-network-graph/
MIT License
480 stars 44 forks source link

[FEAT] ctrlclick event #107

Closed Julien-cpsn closed 1 year ago

Julien-cpsn commented 1 year ago

Hi!

It would be really great to implement a ctrl + click event on nodes, edges and paths. Adding some more events such as keydown/up may be a good idea too!

dash14 commented 1 year ago

Hi @Julien-cpsn, Thanks for the feature request! Currently, it is still possible to detect Ctrl key presses in click events such as "node:click". An example of obtaining Ctrl+click is shown below, which changes the color of the node.

<script setup lang="ts">
import { reactive } from "vue"
import { EventHandlers } from "v-network-graph"
import data from "./data"

const nodes = reactive({ ...data.nodes })

const eventHandlers: EventHandlers = {
  "node:click": ({ node, event }) => {
    if (event.ctrlKey) {
      // toggle
      nodes[node].active = !nodes[node].active
    }
  },
  "node:contextmenu": ({event}) => {
    // Disable the context menu that appears when pressing the Ctrl-key
    // and clicking at the same time in some browsers.
    event.preventDefault();
  }
}
</script>

<template>
  <v-network-graph
    :nodes="nodes"
    :edges="data.edges"
    :layouts="data.layouts"
    :configs="data.configs"
    :event-handlers="eventHandlers"
  />
</template>
// data.ts
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"

const nodes: Nodes = {
  node1: { name: "Node 1", active: false },
  node2: { name: "Node 2", active: false },
  node3: { name: "Node 3", active: true },
  node4: { name: "Node 4", active: false },
}

const edges: Edges = {
  edge1: { source: "node1", target: "node2" },
  edge2: { source: "node2", target: "node3" },
  edge3: { source: "node3", target: "node4" },
}

const layouts: Layouts = {
  nodes: {
    node1: { x: 0, y: 0 },
    node2: { x: 80, y: 80 },
    node3: { x: 160, y: 0 },
    node4: { x: 240, y: 80 },
  },
}

const configs = defineConfigs({
  node: {
    normal: {
      color: n => n.active ? '#ff5555' : '#4466cc'
    },
    hover: {
      color: n => n.active ? '#ff5555' : '#4466cc'
    }
  }
})

export default {
  nodes,
  edges,
  layouts,
  configs,
}

The v-network-graph library does not support key events, but they can be obtained using the standard HTML/Vue ways. Therefore, it is currently considered unnecessary or of low priority for the library to support them. Below is an example of deleting a selected node/edge using the delete key's up event. In the future, if there are any use cases that are difficult to achieve with these standard ways, key events might be supported.

<script setup lang="ts">
import { reactive, ref } from "vue";
import data from "./data";

const nodes = reactive({ ...data.nodes });
const edges = reactive({ ...data.edges });

const selectedNodes = ref([]);
const selectedEdges = ref([]);

function onDeleteKeyUp() {
  if (selectedNodes.value.length > 0) {
    const names = selectedNodes.value.map((n) => data.nodes[n].name).join(", ");
    const confirmed = confirm(`Are you sure you want to delete [${names}]?`);
    if (confirmed) {
      selectedNodes.value.forEach((n) => delete nodes[n]);
    }
  } else if (selectedEdges.value.length > 0) {
    const ids = selectedEdges.value.join(", ");
    const confirmed = confirm(`Are you sure you want to delete [${ids}]?`);
    if (confirmed) {
      selectedEdges.value.forEach((e) => delete edges[e]);
    }
  }
}
</script>

<template>
  <!-- The `tabindex` attribute is required to fire key events. -->
  <v-network-graph
    tabindex="0"
    :nodes="nodes"
    :edges="edges"
    :layouts="data.layouts"
    :configs="data.configs"
    v-model:selectedNodes="selectedNodes"
    v-model:selectedEdges="selectedEdges"
    @keyup.delete="onDeleteKeyUp"
  />
</template>

<style lang="scss" scoped>
.v-network-graph:focus {
  // focus style
  outline: 1px dashed #aaa;
}
</style>
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph";

const nodes: Nodes = {
  node1: { name: "Node 1", active: false },
  node2: { name: "Node 2", active: false },
  node3: { name: "Node 3", active: true },
  node4: { name: "Node 4", active: false },
};

const edges: Edges = {
  edge1: { source: "node1", target: "node2" },
  edge2: { source: "node2", target: "node3" },
  edge3: { source: "node3", target: "node4" },
};

const layouts: Layouts = {
  nodes: {
    node1: { x: 0, y: 0 },
    node2: { x: 80, y: 80 },
    node3: { x: 160, y: 0 },
    node4: { x: 240, y: 80 },
  },
};

const configs = defineConfigs({
  node: {
    selectable: true,
  },
  edge: {
    selectable: true,
  },
});

export default {
  nodes,
  edges,
  layouts,
  configs,
};

I will post these codes in the docs soon. Thank you!

dash14 commented 1 year ago

I will post these codes in the docs soon.

I have added the following URL and will close this issue. https://dash14.github.io/v-network-graph/examples/event.html#handle-user-clicking-on-a-node https://dash14.github.io/v-network-graph/examples/event.html#keyboard-events