Home  >  Q&A  >  body text

Using tags to force direct layout in VEGA

I'm trying to create a network diagram in VEGA using a force-directed layout that displays labels for each node. A possible approach is mentioned in this question. By referring to the Vega editor, we can observe that the labels are present, but there are some overlapping and visual clutter issues.

So I was wondering if it was possible to achieve something similar to this example, where labels appear when hovering over a node and remain highlighted and fixed in the diagram.

I tried some changes in the "Text" field, but I guess it might be more complicated than that.

P粉882357979P粉882357979235 days ago365

reply all(2)I'll reply

  • P粉197639753

    P粉1976397532024-02-27 11:22:03

    Use this configuration:

    {
      "$schema": "https://vega.github.io/schema/vega/v5.json",
      "description": "A node-link diagram with force-directed layout, depicting character co-occurrence in the novel Les Misérables.",
      "width": 700,
      "height": 500,
      "padding": 0,
      "autosize": "none",
    
      "signals": [
        { "name": "cx", "update": "width / 2" },
        { "name": "cy", "update": "height / 2" },
        { "name": "nodeRadius", "value": 8,
          "bind": {"input": "range", "min": 1, "max": 50, "step": 1} },
        { "name": "nodeCharge", "value": -30,
          "bind": {"input": "range", "min":-100, "max": 10, "step": 1} },
        { "name": "linkDistance", "value": 30,
          "bind": {"input": "range", "min": 5, "max": 100, "step": 1} },
        { "name": "static", "value": true,
          "bind": {"input": "checkbox"} },
        {
          "description": "State variable for active node fix status.",
          "name": "fix", "value": false,
          "on": [
            {
              "events": "symbol:mouseout[!event.buttons], window:mouseup",
              "update": "false"
            },
            {
              "events": "symbol:mouseover",
              "update": "fix || true"
            },
            {
              "events": "[symbol:mousedown, window:mouseup] > window:mousemove!",
              "update": "xy()",
              "force": true
            }
          ]
        },
        {
          "description": "Graph node most recently interacted with.",
          "name": "node", "value": null,
          "on": [
            {
              "events": "symbol:mouseover",
              "update": "fix === true ? item() : node"
            }
          ]
        },
        {
          "description": "Flag to restart Force simulation upon data changes.",
          "name": "restart", "value": false,
          "on": [
            {"events": {"signal": "fix"}, "update": "fix && fix.length"}
          ]
        }
      ],
    
      "data": [
        {
          "name": "node-data",
          "url": "data/miserables.json",
          "format": {"type": "json", "property": "nodes"}
        },
        {
          "name": "link-data",
          "url": "data/miserables.json",
          "format": {"type": "json", "property": "links"}
        }
      ],
    
      "scales": [
        {
          "name": "color",
          "type": "ordinal",
          "domain": {"data": "node-data", "field": "group"},
          "range": {"scheme": "category20c"}
        }
      ],
    
      "marks": [
        {
          "name": "nodes",
          "type": "symbol",
          "zindex": 1,
    
          "from": {"data": "node-data"},
          "on": [
            {
              "trigger": "fix",
              "modify": "node",
              "values": "fix === true ? {fx: node.x, fy: node.y} : {fx: fix[0], fy: fix[1]}"
            },
            {
              "trigger": "!fix",
              "modify": "node", "values": "{fx: null, fy: null}"
            }
          ],
    
          "encode": {
            "enter": {
              "fill": {"scale": "color", "field": "group"},
              "stroke": {"value": "white"}
            },
            "update": {
              "size": {"signal": "2 * nodeRadius * nodeRadius"},
              "cursor": {"value": "pointer"}
            }
          },
    
          "transform": [
            {
              "type": "force",
              "iterations": 300,
              "restart": {"signal": "restart"},
              "static": {"signal": "static"},
              "signal": "force",
              "forces": [
                {"force": "center", "x": {"signal": "cx"}, "y": {"signal": "cy"}},
                {"force": "collide", "radius": {"signal": "nodeRadius"}},
                {"force": "nbody", "strength": {"signal": "nodeCharge"}},
                {"force": "link", "links": "link-data", "distance": {"signal": "linkDistance"}}]
            }
          ]
        },
        {
          "type": "text",
          "from": {"data": "nodes"},
          "zIndex": 2,
          "encode": {
            "enter": {
              "align": {"value": "center"},
              "baseline": {"value": "middle"},
              "fontSize": {"value": 15},
              "fontWeight": {"value": "bold"},
              "fill": {"value": "black"},
              "text": {"field": "datum.name"}
            },
            "update": {"dx": {"field": "x"}, "dy": {"field": "y"}}
          }
        },
        {
          "type": "path",
          "from": {"data": "link-data"},
          "interactive": false,
          "encode": {
            "update": {
              "stroke": {"value": "#ccc"},
              "strokeWidth": {"value": 0.5}
            }
          },
          "transform": [
            {
              "type": "linkpath",
              "require": {"signal": "force"},
              "shape": "line",
              "sourceX": "datum.source.x", "sourceY": "datum.source.y",
              "targetX": "datum.target.x", "targetY": "datum.target.y"
            }
          ]
        }
      ]
    }

    reply
    0
  • P粉818306280

    P粉8183062802024-02-27 00:19:46

    I'm not quite sure what you're asking for. I created this force directed diagram and added the tags here:

    https://vega.github.io/vega/examples/packaged bubble chart/

    This is a force directed layout I created using dynamic tags as well.

    https://github.com/PBI-David/Deneb-Showcase

    Are these helpful?

    reply
    0
  • Cancelreply