Adjusting the demonstration of the d3 force-directed graph

Recently, I have started learning about javascript and D3.js, and I am eager to grasp their functionalities. My current focus is on experimenting with the force-directed graph example available at: http://bl.ocks.org/mbostock/4062045

My goal is to modify the JSON data by replacing the array numbers with actual node names. This adjustment is crucial for visualizing a small network topology where I have already set up the node neighbors. Here is the JSON data I intend to use:

{
  "nodes":[
    {"name":"stkbl0001","group":1},
    {"name":"stkbl0002","group":1},
    {"name":"stkbl0003","group":1},
    {"name":"stkbl0004","group":1},
    {"name":"stkbl0005","group":1}
  ],
  "links":[
    {"source":"stkbl0001","target":"stkbl0005","value":3},
    {"source":"stkbl0002","target":"stkbl0005","value":3},
    {"source":"stkbl0003","target":"stkbl0005","value":3},
    {"source":"stkbl0004","target":"stkbl0005","value":3}
  ]

Despite my efforts, I am unable to figure out how to modify the D3 code to incorporate these changes seamlessly. The part where the array numbers are retrieved and connected as links remains obscure to me. While I acknowledge that this may seem like a trivial query, any assistance in this matter would be greatly appreciated!

EDIT:

Below is the current state of the javascript code, following the suggestions provided by Lars Kotthoff:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.node {
  stroke: #fff;
  stroke-width: 1.5px;
}

.link {
  stroke: #999;
  stroke-opacity: .6;
}

</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

var width = 960,
    height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("mini.json", function(error, graph) {
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

  var link = svg.selectAll(".link")
      .data(graph.links)
      .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = svg.selectAll(".node")
      .data(graph.nodes)
      .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

  var nodeMap = {};
  graph.nodes.forEach(function(d) { nodeMap[d.name] = d; });

  graph.links.forEach(function(l) {
      l.source = nodeMap[l.source];
      l.target = nodeMap[l.target];
  })

  node.append("title")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});
</script>

On line 55, the code encounters an error (nodes.forEach(function(d) { nodeMap[d.name] = d; });) with the following message:

Uncaught ReferenceError: nodes is not defined

Answer №1

Check out this link for a live example based on your input.

The code that is crucial to the operation is placed just before initializing the force layout:

var nodeMap = {};

graph.nodes.forEach(function(d) { nodeMap[d.name] = d; });

graph.links.forEach(function(l) {
    l.source = nodeMap[l.source];
    l.target = nodeMap[l.target];
})

force.nodes(graph.nodes)
    .links(graph.links)
    .start();

This will allow you to adapt your data format in a similar way to the original format, making it easy to utilize existing examples from the internet.

(I didn't use a JSON file in my example due to jsfiddle restrictions; instead, I created a function getData() to return the data. However, this should not affect your implementation; you can make it work with JSON files as well)

I hope this information is useful to you.

Answer №2

In the D3 framework, there are two methods for specifying link source and target within the force layout. The first approach, demonstrated in the linked example, involves providing the index of the node in the array of nodes. As the force layout initializes, this index is then replaced with a direct reference to the corresponding node. The alternative method is to explicitly provide the reference to the actual node.

If you wish to reference a node by its name, you must establish a mechanism to resolve that reference. One way to achieve this is shown below:

var nodeMap = {};
graph.nodes.forEach(function(d) { nodeMap[d.name] = d; });

With this mapping in place, you can then proceed to update the links accordingly:

graph.links.forEach(function(l) {
  l.source = nodeMap[l.source];
  l.target = nodeMap[l.target];
})

Furthermore, you can predefine the links using the nodeMap object, for example:

"links":[
 {"source":nodeMap["node1"],"target":nodeMap["node2"],"value":5}
]

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

Issues with jQuery .on() hover functionality in HTML5 select element not being resolved

I'm currently working on capturing the event triggered when the mouse hovers over a select box, regardless of whether it's collapsed or expanded. My approach involves using .on() in the following manner: $(document).on('hover', "select ...

Is there a way to insert a secured page right before accessing the dashboard?

I am trying to create a locked page that will display a message when users access the web app from a mobile device and load a mobile layout page displaying a message like mobile is not supported. I was considering using document.addEventListener('DOMC ...

Identify the element in the array that corresponds to the current route

Within an array, I have various routes such as: /app/manual/:id /app/manuals/:id /app/feedback ... In my react.js application, I am looking to compare the location.pathname with the paths in my array and retrieve the title associated with the matching pa ...

Challenges in creating an alternative path in ExpressJS

I am currently working on a website for my studies. I decided to use nodejs/Express, as the technology is free. The first route /home was successful, but I am having trouble creating more routes. https://i.sstatic.net/6oseq.png Although I thought I had a ...

Steps to ensure that a particular tab is opened when the button is clicked from a different page

When I have 3 tabs on the register.html page, and try to click a button from index.html, I want the respective tab to be displayed. Register.html <ul class="nav nav-tabs nav-justified" id="myTab" role="tablist"> <l ...

Display a progress bar that shows completion based on the maximum value supplied

I successfully created a progress bar using HTML, CSS, and Javascript. It functions perfectly up to a provided value of 100. However, if a value higher than 100 is given, the progress completes but the value continues to change until it reaches the maximum ...

How to extract a one-of-a-kind identification number from the browser using just JavaScript in a basic HTML file?

Is there a way to obtain a distinct identification number from a browser without resorting to techniques such as generating and storing a unique number in cookies or local storage, and without utilizing a server-side language? ...

Response coming from an ajax call in the form of a JSON

With the JSON string provided below: {cols:[{"id":"t","label":"Title","type":"string"},{"id":"l","label":"Avg ","type":"string"},{"id":"lb","label":"High","type":"string"},{"id":"lo","label":"Low","type":"string"}],rows:[{"c":[{"v":"Change navigation"},{"v ...

Utilizing JSON object nesting to organize the results of PostgreSQL relational queries

There are three tables in my database: "parent", "children", and "grandchildren". These tables have many-to-many relationships. In addition to the main tables, there are also two relational tables. I want to create a query that will return all parent elem ...

Steps for raising a unique error in an asynchronous callout

As I work on making async API callouts, there might be a need to throw custom errors based on the outcome. Also, part of this process involves deleting objects from S3. try { await s3.deleteObject(bucketParams); //Since S3 API does not provide ...

Error occurred when trying to import an external module using an invalid hook call

I am creating a package named "Formcomponent" using React and React Bootstrap. This code is from index.tsx /** * Renders a component for a form. */ import React from "react"; import Form from "react-bootstrap/Form"; /** * List of props * @returns */ ...

"Utilize an HTML input to query and retrieve data stored in a

Seeking to retrieve data from my MySQL database and display it on the website securely. List of existing files: /includes db_connect.php functions.php getdata.php logout.php process_login.php psl-config.php register.inc.php /j ...

Error encountered during Heroku deployment: "sh: 1: tailwind: not found"

package.json: "devDependencies": { "tailwindcss": "^0.7.4" }, "scripts": { "tailwind:css": "tailwind build src/css/tailwind.src.css -c tailwind.js -o src/css/tailwind.css", "start": "npm run tailwind:css && react-scripts start", ...

The Facebook SDK fails to activate in Internet Explorer

I am currently working on implementing a Facebook login using the JavaScript SDK. Everything is functioning correctly in most browsers, but I am experiencing issues with certain versions of Internet Explorer. The login functionality is not working on my l ...

establishConnection(); ^ TypeError: establishConnection is undefined

While attempting to connect to MongoDB, I encountered an error in my index.js file. require('dotenv').config(); const express = require('express') const app = express(); const cors = require('cors'); const connection = require ...

Tips for overcoming a script error within the body of a Next.js project

I encountered an error in my _document.js file when trying to add a script to the body of my document. Here is the specific error message that was returned: https://i.stack.imgur.com/QG5zb.png ./pages/_document.js Error: x Expected '}', got &a ...

Utilizing multiple UILocalNotifications simultaneously

Hey there, I've encountered an issue with using UILocalNotification. I'm receiving notifications from a server and storing the data in a MutableArray. Here's a snippet of what it looks like: idnoty * id of notification titlenoty * title of ...

Are toggle functionalities triggered when an element is clicked?

How come the span triggers functions a and b when first clicked, is there a way to set it up so that it calls function a on the first click and then function b on the second click? function a(id) { $.post("url.php", {'id':id}, function() { ...

When attempting to redirect to a different page using setTimeout, the loading process appears to continue indefinitely

Currently, I am utilizing the following script: setTimeout(function(){ window.location.href = '/MyPage'; }, 5000); While this script successfully redirects me to /MyPage, it continuously reloads every 5 seconds. Is there a way to r ...

Setting a CSS Variable with the Help of jQuery

I need help with changing the background color of a specific .div element when it is clicked on. I want the color to be a variable that can be changed by the user, and this change should occur when the document is ready. Currently, I am using a CSS variab ...