dash14 / v-network-graph

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

How can I listen to the event of click on label(both node label and edge label)? #72

Closed Luciennnnnnn closed 1 year ago

Luciennnnnnn commented 2 years ago

I would to provide the user interface so they can modify label interactively.

Luciennnnnnn commented 2 years ago

@dash14 Hi, is this possible to implement?

dash14 commented 2 years ago

Hi @LuoXin-s, It is possible to use override-node-label slot and edge-label slot to retrieve events. However, it requires writing a bit of tricky code to listen the events, and may add the feature to be able to handle events in the future...

The following is an example of handling a click event with the current version of the v-network-graph.

<!-- App.vue -->
<script setup lang="ts">
import data from "./data";

function onClickNodeLabel(nodeId: string) {
  console.log("Clicked node label:", nodeId);
}

function onClickEdgeLabel(edgeId: string) {
  console.log("Clicked edge label:", edgeId);
}
</script>

<template>
  <v-network-graph
    :nodes="data.nodes"
    :edges="data.edges"
    :layouts="data.layouts"
  >
    <template
      #override-node-label="{
        nodeId,
        scale,
        text,
        x,
        y,
        config,
        textAnchor,
        dominantBaseline,
      }"
    >
      <!-- Since the label is part of the node area, the pointerdown event
        is also stopped to avoid detection as a node click. -->
      <text
        class="custom-node-label"
        :x="x"
        :y="y"
        :font-size="config.fontSize * scale"
        :text-anchor="textAnchor"
        :dominant-baseline="dominantBaseline"
        :fill="config.color"
        @pointerdown.stop=""
        @click.prevent="onClickNodeLabel(nodeId)"
        >{{ text }}</text
      >
    </template>
    <template #edge-label="{ edgeId, edge, ...slotProps }">
      <v-edge-label
        :text="edge.label"
        align="center"
        vertical-align="above"
        v-bind="slotProps"
        @pointerdown.stop=""
        @click="onClickEdgeLabel(edgeId)"
      />
    </template>
  </v-network-graph>
</template>

<style scoped>
.custom-node-label {
  cursor: pointer;
}
::v-deep(.v-edge-label) {
  pointer-events: all !important;
  cursor: pointer !important;
}
</style>
// data.ts
import { Nodes, Edges, Layouts } from "v-network-graph";

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

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

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

export default {
  nodes,
  edges,
  layouts,
};

Best Regards

Luciennnnnnn commented 2 years ago

@dash14 Sorry for the late response, I have other things to do recently. The code snippet looks very clear, I'll try it later.

dash14 commented 1 year ago

I close this issue for now. If you have any questions, please re-open this or open a new issue.