Creating visual representations of class, organization, flow, or state diagrams using Vega or Vega-lite

I'm struggling to find an example of a state, class, flow chart, or org chart diagram created with Vega. Are there any available online?

Vega seems like the perfect tool for this type of visualization, although it may be a bit complex. Without a starting point, the learning curve is quite steep. While there are some examples on the "How Vega Works" page, there aren't links showing how they were made:

https://i.sstatic.net/GmWqt.png

There's also an example using the tree layout, but it's not clear how one would go about adapting it into blocks suitable for a flowchart-style diagram.

https://i.sstatic.net/1mBoY.png

Here are some examples of the desired output (including other shapes like diamonds and triangles) from mermaid.js:

https://i.sstatic.net/71gkE.png

Answer №1

Imagine if you could visualize your data in a structured chart like this:

"values": [
        {"id": "1", "parent": null, "title": "Animal"},
        {"id": "2", "parent": "1", "title": "Duck"},
        {"id": "3", "parent": "1", "title": "Fish"},
        {"id": "4", "parent": "1", "title": "Zebra"}
      ]

Once you have your nodes arranged in a tree-like layout using the stratify function:

"transform": [
        {
          "type": "stratify",
          "key": "id",
          "parentKey": "parent"
        },
        {
          "type": "tree",
          "method": "tidy",
          "separation": true,
          "size": [{"signal": "width"}, {"signal": "height"}]
        }
      ]

For creating connecting lines between nodes, use treelinks along with linkpath to generate them:

{
      "name": "links",
      "source": "tree",
      "transform": [
        { "type": "treelinks" },
        { "type": "linkpath",
          "shape": "diagonal"
          }
      ]
    }

Next step is to represent the data visually using marks in Vega. Here, I'm keeping it simple by drawing rectangles and text labels for each node:

"marks": [
    {
      "type": "path",
      "from": {"data": "links"},
      "encode": {
        "enter": {
          "path": {"field": "path"}
        }
      }
    },
    {
      "type": "rect",
      "from": {"data": "tree"},
      "encode": {
        "enter": {
          "stroke": {"value": "black"},
          "width": {"value": 100},
          "height": {"value": 20},
          "x": {"field": "x"},
          "y": {"field": "y"}
        }
      }
    },
    {
      "type": "text",
      "from": {"data": "tree"},
      "encode": {
        "enter": {
          "stroke": {"value": "black"},
          "text": {"field": "title"},
          "x": {"field": "x"},
          "y": {"field": "y"},
          "dx": {"value":50},
          "dy": {"value":13},
          "align": {"value": "center"}
        }
      }
    }
  ]
}

While the output might not match exactly, this basic setup provides an approximation of your target visualization. To render different shapes for root and leaf nodes, you can apply filters on the dataset and adjust the mark types accordingly:

{
      "name": "tree-boxes",
      "source": "tree",
      "transform": [
          { 
            "type": "filter",
            "expr": "datum.parent == null"
          }
        ]
    },
    {
      "name": "tree-circles",
      "source": "tree",
      "transform": [
        {
          "type": "filter",
          "expr": "datum.parent != null"
        }
      ]
    },
    {
      "type": "rect",
      "from": {"data": "tree-boxes"},
      "encode": {
        "enter": {
          "stroke": {"value": "black"},
          "width": {"value": 100},
          "height": {"value": 20},
          "x": {"field": "x"},
          "y": {"field": "y"}
        }
      }
    },
    {
      "type": "symbol",
      "from": {"data": "tree-circles"},
      "encode": {
        "enter": {
          "stroke": {"value": "black"},
          "width": {"value": 100},
          "height": {"value": 20},
          "x": {"field": "x"},
          "y": {"field": "y"}
        }
      }
    }

Answer №2

For a comprehensive guide on working with trees, you can check out the solution provided at this link.

This tutorial will take you through:

Step 1 - Extracting Nodes from Tabular Data

Step 2 - Extracting Links from Stratified Node Data

Step 3 - Bringing them together effectively

Step 4 - Adding labels for better visualization

Step 5 - Enhancing the display with color

Answer №3

I have created a demonstration that closely matches the description in this question. My solution was inspired by the accepted answer provided here, thanks to @timur.

Here is the Vega Editor link where you can see it in action.

The example showcases tree nodes as groups with multiple texts inside. It allows for expanding and collapsing of nodes, as well as switching between horizontal and vertical layouts (you can control this by adjusting the default value of the horizontal signal).

However, I did encounter some limitations:

  • Switching between horizontal and vertical layouts may not render all marks correctly unless the default value of the horizontal signal is manually changed in the code (an issue has been raised here)
  • I struggled to find a way to collapse the root node of the tree properly without manually collapsing nested nodes (I posted a related question here)

Regardless, this should be beneficial for anyone interested in creating an Org Chart-style visualization using Vega. Without closer examples, I had to dedicate numerous hours to uncover all the nuances and address nearly every issue encountered.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to halt execution in Express.js following an error caught from an Await request?

While searching for a solution, I come across many posts that almost provide the answer I need, but nothing seems to quite work in my case. I have a function that uses asynchronous operations: const doStuff = async (data)=>{ if(data == "a bug& ...

Issue with Google Finance JSON response not functioning as expected in Chrome and Firefox browsers, yet appears to be working properly in

I am currently working on a JavaScript project that involves fetching STOCK data from the Google Finance API. When I manually paste the link into my browser, I can successfully retrieve the JSON response: // [ { "id": "22144" ,"t" : "AAPL" ,"e" : "NASDAQ ...

What causes the alignment of text to be overridden by the presence of a floating element?

https://jsfiddle.net/u0Ltgh3e/68/ .text { width: 50%; text-align: justify; } I am currently developing a custom formatting tool for a specific purpose and I am attempting to create a two-column layout similar to the one demonstrated in this Jsfiddle l ...

How can I retrieve the updated input value once a specific key has been pressed in the prototype?

After a customer presses any key, I would like to check an email. Below is the code I am using: document.observe("dom:loaded", function() { $('billing:email').observe('keypress', function(event){ console.log(event.element(). ...

The content in the div tag isn't showing up properly because of Ajax

I am facing an issue with my Ajax query. Even though I can retrieve the results by posting, they are not displaying in the designated div tag on mainInstructor2.php. Instead, the results are showing up on a different page - specifically, on InstructorStude ...

Tips for retrieving the MenuItem name upon click event using Menu and MenuItem components in Material UI React

Utilizing MaterialUI's Menu and MenuItem components in a React project, I am looking to display the name of the menu item upon clicking on it. Upon inspecting event.currentTarget in console.log, it returns the entire list item: ListItem Image attache ...

Encountering an issue with an AngularJS form containing ng-repeat when attempting to submit

Here is my form structure: two text inputs followed by an ng-repeat with a text input and radio button inside. <form class="form-horizontal" id="myForm" name="myForm"> <div class="form-group"> <label for="name" class="co ...

Utilizing jQuery AJAX to efficiently handle branching based on the result received

I've successfully set up my first AJAX call with jQuery. The only thing left to do is to check the result from the PHP page for any database errors and display an error message if necessary. Here's the current Javascript code: <script type=" ...

Determining when a checkbox changes state using HTML and JavaScript

My main objective is to display divX2 when the checkbox for x2 is checked, either by directly clicking on x2 or by clicking on the "Check All" checkbox. The functionality works as intended when the checkbox for x2 is clicked, but it fails to work when the ...

Switching the active className in React and Next.js based on selection status

My goal is to dynamically change the className of each Card component when clicked on. When one Card is selected, the others should revert back to their default className. This is my UserBookingData component: const UserBookingData = ({ bookings }: any) = ...

Having trouble seeing the Facebook registration page on Firefox?

Encountering some issues with Facebook and Firefox. Specifically, the registration popup on Facebook always appears empty when using Firefox. I have tried different approaches to the popup code but so far, nothing seems to be resolving the issue. Is there ...

Locate and extract the JSON object using the specified key-value pair

Trying to extract a specific object from a complex json file, noting the key, and then returning a new json poses a challenge. I am using expressjs as the backend for this task. Sample.json '[{"ServID":"Rai 1","Parametri" ...

Solving SEO issues with jQuery load()

I have developed a modal window that includes links, but unfortunately, search engine crawlers are unable to read and index those links. I am looking for a solution to make sure the crawler can index those links. I have noticed websites using AngularJS li ...

How can I resolve the issue of the input field added dynamically by JavaScript not appearing in the PHP $_POST variable?

I have a form nested within an HTML table. Using jQuery, I am dynamically adding input fields to the form. However, when I submit the form and check the $_POST array with var_dump(), the added fields are not showing up. Why is this happening? Below is th ...

Displaying a picture solely in a designated region

I created a basic menu using an unordered list: <ul class="courses"> <a href="#"> <li class="spinny"> <h3>Course Title</h3> <img class="rotateme" src="images/logo_transparent.png"/> </li& ...

Meteor.js in conjunction with ScrollMagic TweenMax.to

Having trouble getting Meteor template.rendered to work with ScrollMagic I am trying to make this code function properly. if (Meteor.isClient) { Meteor.startup(function () { scrollMagicController = new ScrollMagic(); Template.StartAnimatio ...

JavaScript for loop similar to Python'sIn JavaScript, the

As someone who is new to programming, I primarily use Python but have now encountered a situation where I need to work with JavaScript for a project utilizing Phonegap. The query retrieved from the server looks like this: [["CompanyName", "lat", "long", ...

Guide for setting up a React infinite scroll feature in a messaging app similar to Facebook Messenger

I have been exploring various questions regarding React infinite scroll, but I am looking to delve deeper in order to discover the most effective solution available for implementing such a component. Currently, I am working on a chat application and have ...

Navigating through this object with PUG and Express: a step-by-step guide

I am currently working on a basic blockchain project to practice my skills with nodejs. I have created a blockchain object that consists of a block class, and now I want to loop through this object using pug. app.get('/', function(request, respon ...

What could be causing variations in the performance of my Speech Recognition code each time I run it?

Check out my code snippet: export class voiceRecognition { constructor() { } public startVoiceRecognition() { const recognition = new webkitSpeechRecognition(); recognition.continuous = false; recognition.interimresults = false; recogn ...