Exploring the creation of a dynamic graph with d3.js

I'm new to d3 and attempting to create a graph layout.

        var w = 1000;
        var h = 500;
        var dataset = {
            nodes: [{
                name: 'Alice'
            }, {
                name: 'David'
            }, {
                name: 'Eve'
            }],
            edges: [{
                source: 0,
                target: 1
            }, {
                source: 1,
                target: 2
            }]
        };
        var svg = d3.select("body")
            .append("svg")
            .attr("height", h)
            .attr("width", w);

        var force = d3.layout.force()
            .nodes(dataset.nodes)
            .links(dataset.edges)
            .size([w, h])
            .linkDistance([50])
            .start();

        var nodes = svg.selectAll("circle")
            .data(dataset.nodes)
            .enter()
            .append("circle")
            .attr("r", 10)
            .style("fill", "blue")
            .call(force.drag);

        var edges = svg.selectAll("line")
            .data(dataset.edges)
            .enter()
            .append("line")
            .style("stroke", "#999")
            .style("stroke-width", 2);

You can view my fiddle here: http://jsfiddle.net/username/example/

I'm having trouble getting the graph to display correctly. Any advice or suggestions would be greatly appreciated.

Answer №1

1. Ensure that the cx and cy of the circle are set in order to position it correctly. 2. Set x1, y1, x2, and y2 of the line to properly position the line.

3. To activate the layout, listen for the tick event of the force layout.

            
var w = 300;
var h = 300; 
var dataset = {
    nodes: [{
        name: 'Aden'
    }, {
        name: 'Bob'
    }, {
        name: 'Sue'
    }],
    edges: [{
        source: 0,
        target: 1
    }, {
        source: 1,
        target: 2
    }]
};
var svg = d3.select("body")
    .append("svg")
    .attr("height", h)
    .attr("width", w);

var force = d3.layout.force()
    .nodes(dataset.nodes)
    .links(dataset.edges)
    .size([w, h])
    .on("tick", tick) 
    .linkDistance([50])
    .start();

var nodes = svg.selectAll("circle")
    .data(dataset.nodes)
    .enter()
    .append("circle")
    .attr("r", 10)
    .attr("cx", function (d) {return d.x; })
    .attr("cy", function (d) { return d.y; })
    .style("fill", "red")
    .call(force.drag);

var edges = svg.selectAll("line")
    .data(dataset.edges)
    .enter()
    .append("line")
    .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;
    })
    .style("stroke", "#ccc")
    .style("stroke-width", 1);

function tick(e) {
     edges.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; });

  nodes.attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
}

Demo Update: http://jsfiddle.net/MnX23/3/

Answer №2

When working with circles in SVG, it is important to specify the attributes cx and cy, as well as the line attributes x1,y1,x2,y2.

  • The x1 attribute determines the starting point of the line on the x-axis
  • The y1 attribute determines the starting point of the line on the y-axis
  • The x2 attribute determines the ending point of the line on the x-axis
  • The y2 attribute determines the ending point of the line on the y-axis

Feel free to test out this code:

DEMO

   var width = 1000;
        var height = 500;
        var data = {
            nodes: [{
                name: 'Aden'
            }, {
                name: 'Bob'
            }, {
                name: 'Sue'
            }],
            edges: [{
                source: 0,
                target: 1
            }, {
                source: 1,
                target: 2
            }]
        };
        var svgCanvas = d3.select("body")
            .append("svg")
            .attr("height", height)
            .attr("width", width);

        var simulation = d3.layout.force()
            .nodes(data.nodes)
            .links(data.edges)
            .size([width, height])
            .linkDistance([50])
            .start();

        var nodeElements = svgCanvas.selectAll("circle")
            .data(data.nodes)
            .enter()
            .append("circle")
            .attr("r", 10)
            .style("fill", "red")

            .call(simulation.drag);

        var edgeElements = svgCanvas.selectAll("line")
            .data(data.edges)
            .enter()
            .append("line")

            .style("stroke", "#ccc")
            .style("stroke-width", 1);

       simulation.on("tick", function() {
       edgeElements.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; });

      nodeElements.attr("cx", function(d) { return d.x; })
                  .attr("cy", function(d) { return d.y; });
            });

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

Ways to refresh the main frame

Here is an example of parent code: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Parent</title> </head> <body> <iframe src="https://dl.dropboxusercontent.com/u/4017788/Labs/child.html" width ...

Finding the correlation between SVG element IDs and JSON keysUnderstanding how to pair up

Currently, I have an SVG file that can be viewed here. My goal is to present specific data when elements within the SVG are clicked. The data is in JSON format and I am looking to match each ID of an SVG element with a key in the JSON data. If both the key ...

Challenges with the Placement of Buttons

I am facing an issue with the code below: document.addEventListener("DOMContentLoaded", function(event) { // Select all the read more buttons and hidden contents const readMoreButtons = document.querySelectorAll(".read-more"); const hiddenConten ...

Revise the reply within ExpressJS

I need help with editing the response to a request in Express. When the request is made via XHR, I want to encapsulate the body inside a JavaScript object. This way, different parts of the page can be accessed individually within the JavaScript object, suc ...

Merging two arrays concurrently in Angular 7

When attempting to merge two arrays side by side, I followed the procedure below but encountered the following error: Cannot set Property "account" of undefined. This is the code in question: acs = [ { "account": "Cash In Hand", ...

Assign the two values to variables in the CSS script

My challenge lies in passing two values to the CSS within the <style> tags. The values are: (background-color: --placeholder; color: --placeholdtext;). I am able to pass either one of the values successfully, but not both at the same time. When I cop ...

"Jquery's .append function may sometimes display as undefined when

$("#clckjson").click(function() { $(document).ready(function() { $.getJSON("fuelj.json", function(data) { $(data).each(function(i, item) { console.log(item.stationID); var $table = $('<table>'); $table.a ...

Trigger an event when the menu is outside the viewport and then lock the menu to the top of the viewport

I am trying to create a menu element that remains fixed at the top of the browser viewport as the user scrolls, ensuring it is always visible. In my webpage layout, the menu sits below some text in the header initially. Once the user scrolls past the heade ...

Execute the getJSON calls in a loop for a count exceeding 100, and trigger another function once all

In order to process a large grid of data, I need to read it and then make a call to a $getJSON URL. This grid can contain over 100 lines of data. The $getJSON function returns a list of values separated by commas, which I add to an array. After the loop fi ...

Retrieving Twitter posts using the screen_name parameter in a Node.js environment

I am looking to create a website that allows users to enter the Twitter screen name of any celebrity. When the user clicks on the "show tweet" button, the latest tweet from that screen name will be displayed. I am interested in implementing this feature ...

Issue in Next.js 13: Byte index exceeds limits when running 'npm run dev' command

When attempting to install Next.js 13.4.12, I utilized the command npx <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="385b4a5d594c5d15565d404c1559484878090b160c1609">[email protected]</a>. The installation process ...

The AJAX request encountered an unexpected failure that cannot be identified (Using jQuery)

Are you facing issues with a service that returns JSON data? Check out this URL: If you're attempting a simple AJAX request, here's some sample code to get you started: $.ajax({ type: "get", url: "http://api.drag2droid.shamanland.com/ca ...

Index similar to JavaScript-Meadow

Is there a way to create a table of contents like the ones seen on sites such as JavaScript Gardens? How do they determine which section is currently active and are there any recommended JavaScript libraries that can help achieve this functionality? Edit: ...

What is the best way to organize a table with multiple state variables using nested loops?

What is the best way to display multiple variables in a table using a loop, such as i,j,k? this.state = { materials: ['m1', 'm2'], quantity: ['2', '4'], unitPrice : ['12&apo ...

Hide all elements in jQuery that do not have a class assigned

I've implemented a straightforward jQuery script that toggles the "active" class on an li element when it is clicked: $('li').click(function() { $(this).toggleClass('active'); }); My goal is to hide all other li elements in t ...

Generating and saving a text file in a React Native application

Is there a way to convert a string into a text file within the client application and then download it directly onto a phone? If so, how can this be achieved? ...

enhancement in bringing in ... from

Hey there, I've been working with Vue.js and came across an interesting challenge. In order to use components in Vue.js, you usually need to import them individually. I thought of a solution where we could create a module containing paths to all the c ...

Anticipated spatial glitch problem involving the gadicc/meteor-reactive-window package for Meteor

Utilizing the gadicc/meteor-reactive-window Meteor Package to switch templates based on screen size. This file is named pictureDisplatSection.html <template name="pictureDisplaySection"> <div class="display"> ...

Is there a way I can ensure the values are loaded when the page loads, rather than displaying NaN?

I've recently created a car rental calculator for a client, and it's almost complete. Everything is working smoothly, from the calculations to the conditions. However, I'm facing an issue where the price isn't calculated on page load. I ...

The collapsible tree nodes overlap one another in the D3.js visualization

I'm currently working on integrating a d3 code into Power BI for creating a collapsible tree structure. Each node in the tree is represented by a rectangular box, but I've run into an issue where nodes overlap when their size is large. Below is t ...