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

Node width #147

Closed EvgenyFrol closed 2 weeks ago

EvgenyFrol commented 2 months ago

Hi!

How can I set the automatic width of a node based on the filling of the label inside the node? I haven't found an example with a similar case, but in docs said that the width of a node has only some definitely static value

image

Сan you advise me how to solve this problem?

dash14 commented 1 month ago

Hi @EvgenyFrol, I apologize for the delayed response. Although it might be too late, I am providing my answer just in case it is still needed.

The maximum node size must be specified, but this can be accomplished by overriding the node with a <foreignObject> and placing an html element in it that will automatically adjust the size.

The following is an example code and a screenshot.

<script setup lang="ts">
import { Layouts, defineConfigs, Edges, Nodes } from "v-network-graph"

const nodes: Nodes = {
  node1: { name: "Orange" },
  node2: { name: "Strawberry" },
  node3: { name: "Pear" },
}
const edges: Edges = {
  edge1: { source: "node1", target: "node2" },
  edge2: { source: "node2", target: "node3" },
}

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

const configs = defineConfigs({
  node: {
    normal: {
      type: "rect",
      width: 200, // max width
      height: 100, // max height
    },
    label: {
      visible: false,
    }
  }
})
</script>

<template>
  <v-network-graph :nodes="nodes" :edges="edges" :configs="configs" :layouts="layouts">
    <defs>
    <!-- Cannot use <style> directly due to restrictions of Vue. -->
    <component :is="'style'">
      .node-wrapper {
        width: 100%;
        height: 100%;
        display: grid;
        place-items: center;
      }
      .node-element {
        display: grid;
        place-items: center;
        padding: 4px 10px;
        background-color: #ccc;
        border: 1px solid #888;
        border-radius: 6px;
        position: relative;
        pointer-events: all; /* mouse operation target */
      }
    </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})`"
      style="pointer-events: none;"
      v-bind="slotProps">
      <div class="node-wrapper">
        <div class="node-element">
          {{ nodes[nodeId].name }}
        </div>
      </div>
    </foreignObject>
    </template>
  </v-network-graph>
</template>

screenshot

dash14 commented 2 weeks ago

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