dash14 / v-network-graph

An interactive network graph visualization component for Vue 3

Home Page:https://dash14.github.io/v-network-graph/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use Custom Node

Ulrich-Mbouna opened this issue · comments

Hi Thanks you for this Awesome librairie.

I want to know if it's possible to have a custom node (with Div and HTML markup) like this image

image

Because i see the fact all things are render in svg limit the posibility to custom node as we want.

Thanks you 🙏

Hi @Ulrich15,
Thank you for your question!

By using <foreignObject> tag of SVG, nodes can be rendered using html markup and css.
An example is shown below:

<script setup lang="ts">
import { defineConfigs } from "v-network-graph";
import data from "./data";

const configs = defineConfigs({
  node: {
    label: {
      visible: false,
    },
    normal: {
      type: "rect",
      width: 140,
      height: 80,
    }
  }
});

</script>

<template>
  <v-network-graph
    :nodes="data.nodes"
    :edges="data.edges"
    :layouts="data.layouts"
    :configs="configs"
  >
    <defs>
      <!-- Cannot use <style> directly due to restrictions of Vue. -->
      <component :is="'style'">
        .node-div {
          width: calc(100% - 2px); /* 2px for border-width */
          height: calc(100% - 2px); /* 2px for border-width */
          background-color: #ccc;
          border: 1px solid #888;
          border-radius: 6px;
          font-weight: bold;
          position: relative;
          display: flex;
          align-items: center;
          justify-content: center;
        }
      </component>
    </defs>
    <template #override-node="{ nodeId, scale, config, ...slotProps }">
      <foreignObject
        :x="-config.width/2"
        :y="-config.height/2"
        :width="config.width"
        :height="config.height"
        :transform="`scale(${scale})`"
        v-bind="slotProps">
        <div class="node-div">
          <div class="node-div-title">
            {{ data.nodes[nodeId].title }}
          </div>
          <label>{{ data.nodes[nodeId].label }}</label>
        </div>
      </foreignObject>
    </template>
  </v-network-graph>
</template>

<style lang="scss" scoped>
// It is also possible to write styles directly within Vue's <style> as shown below.
// Note that if the generated result is obtained as an svg file using the
// `exportAsSvgText()` function, the following styles will not be included.
.node-div {
  label {
    position: absolute;
    font-size: 10px;
    background-color: red;
    color: white;
    left: 4px;
    top: 4px;
    padding: 2px 4px;
    border-radius: 4px;
  }
}
</style>
// data.ts
import { Nodes, Edges, Layouts } from "v-network-graph"

const nodes: Nodes = {
  node1: { title: "Title 1", label: "Label 1" },
  node2: { title: "Title 2", label: "Label 2" },
  node3: { title: "Title 3", label: "Label 3" },
}

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

const layouts: Layouts = {
  nodes: {
    node1: { x: 100, y: 0 },
    node2: { x: 0, y: 150 },
    node3: { x: 200, y: 150 },
  },
}

export default {
  nodes,
  edges,
  layouts,
}

screenshot

I hope this helps.

I close this issue for now.
If you have any other question/comment, please reopen this issue.