Changing the orientation of nodes in a d3.js diagram

Using d3.js to create a nodes diagram, currently displaying parent on the left and children on the right. Is it possible to reverse this direction so that children are on the left and parents on the right?

Here is the renderTree function used to display the tree node:


vm.renderTree = function (treeData, treeId) {
    // Function code goes here
};

Example of treeData:


{
  "id": 1,
  "code": "a",
  "name": "b",
  "type": "t",
  "leId": 2,
  
  "leName": "d",
  
  "children": [
    {
      "id": 2,
      "code": "e",
      "name": "f",
      "type": "g",
      "leId": 4,
      
      "lename": "e",
      
      "childrenCount": 0
    }
  ],
  "childrenCount": 1
}

Answer №1

Here is a segment of a tree with the opposite direction.

Switch d.y to height - d.y, interchange the positioning of text (start / end) and adjust the call of diagonal for links:

var data = [
    { "name" : "Level 2: A", "parent":"Top Level" },
    { "name" : "Top Level", "parent":"null" },
    { "name" : "Son of A", "parent":"Level 2: A" },
    { "name" : "Daughter of A", "parent":"Level 2: A" },
    { "name" : "Level 2: B", "parent":"Top Level" }
    ];

// *********** Convert flat data into a nice tree ***************
// create a name: node map
var dataMap = data.reduce(function(map, node) {
    map[node.name] = node;
    return map;
}, {});

// create the tree array
var treeData = [];
data.forEach(function(node) {
    // add to parent
    var parent = dataMap[node.parent];
    if (parent) {
        // create child array if it doesn't exist
        (parent.children || (parent.children = []))
            // add node to child array
            .push(node);
    } else {
        // parent is null or missing
        treeData.push(node);
    }
});

// ************** Generate the tree diagram  *****************
var margin = {top: 20, right: 120, bottom: 20, left: 120},
    width = 960 - margin.right - margin.left,
    height = 500 - margin.top - margin.bottom;
    
var i = 0;

var tree = d3.layout.tree()
    .size([height, width]);

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

root = treeData[0];
  
update(root);

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 180; });

  // Declare the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });

  // Enter the nodes.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { 
          return "translate(" + (height - d.y) + "," + d.x + ")"; });

  nodeEnter.append("circle")
      .attr("r", 10)
      .style("fill", "#fff");

  nodeEnter.append("text")
      .attr("x", function(d) { 
          return d.children || d._children ? 13 : -13; })
      .attr("dy", ".35em")
      .attr("text-anchor", function(d) { 
          return d.children || d._children ? "start" : "end"; })
      .text(function(d) { return d.name; })
      .style("fill-opacity", 1);

  // Declare the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });

  // Enter the links.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", d => {
        console.log(d);
       const source = {x: d.source.x, y: height - d.source.y};
       const target = {x: d.target.x, y: height - d.target.y};
         return diagonal({source, target});
     });

}
    .node circle {
      fill: #fff;
      stroke: steelblue;
      stroke-width: 3px;
    }

    .node text { font: 12px sans-serif; }

    .link {
      fill: none;
      stroke: #ccc;
      stroke-width: 2px;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.7/d3.min.js"></script>

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

Error: The property 'postID' can not be read because it is undefined

I'm new to programming and I am working on creating a news/forum site as a practice project. I have set up a route /post/postID/postTitle to view individual posts. Initially, when I used only :postID, it worked fine. But after adding :postTitle, whene ...

Retrieve the date information from the <td> element, if it exists

There are numerous rows in the table. The table cell labeled "dates" may contain either a specific date or the word "Permanent". If there is a date present and it happens to be greater than today's date, it needs to be highlighted in red. I attempted ...

How to trigger a hover effect on a div and its child simultaneously using HTML and jQuery

Here's my concept: I want the text to be contained within div elements with an integrated image, rather than just having fading in and out pictures. Here's my attempt: #first{ position: absolute; } #second{ position: absolute; -we ...

Exploring jQuery Mobile: Uncovering the Power of clientX, clientY, and taphold Event

In my current project, I am implementing the taphold event and require the coordinates of the tapped point by the user. However, I have encountered an issue where event.clientX and event.clientY are returning as undefined (you can see the example here: her ...

How to make a form in PHP that can be saved?

I have put together a straightforward, yet lengthy HTML form and I am in need of a way for users to save their progress on the form and return to it at a later time (security is not a major concern). However, I am struggling with how to save the form' ...

Iterate through each key in the response JSON object using a variable named "a

Here is a snippet of my code: var roomid= roomIds[i] const Availabilitydata = await AvailResponse.json(); availableroomsArray.push(Availabilitydata); app.get("/api/availability", (req, res) => { res.json({ indicateur: availableroomsA ...

Whenever I declare it, the onclick method is executed

I have been attempting to define an onclick method that would trigger a function to clear and reconstruct the display, revealing more detailed information about the clicked item. However, I am facing an issue where the assigned onclick method is executed i ...

developing a dynamic structure that can store multiple levels of data

I am grappling with the task of creating a multidimensional array in JavaScript to send data via an Ajax call to PHP. My expertise in JS is limited, especially when it comes to this particular task... I have shared the code on JSFiddle The desired struct ...

Stretch out single column content vertically in bootstrap for a uniform look

I've been struggling to make multiple buttons vertically stretch to fit the container, but I can't seem to remember how I achieved this in the past. I have experimented with various options outlined on https://getbootstrap.com/docs/4.0/utilities/ ...

What is the best way to display a child component inside an iframe using Vue.js?

Looking to provide a live preview of an email before sending it out, I've opted to use an iframe to contain the preview and prevent style leaks. The goal is for the preview to update dynamically as the user fills out form details. How can I display a ...

Guide on transforming an array object for compatibility with MUI's Autocomplete field

I've encountered a challenge while attempting to transform my incoming object into a format suitable for MUI's Autocomplete component. Here is the current code snippet I am working with: const [contactList, setContactList] = useState([]); useEf ...

Is spine.js truly capable of 'streamlining' POST requests?

I recently came across a post by Alex Maccaw, where he discusses the challenges of sending Ajax requests in parallel: Maccaw explains that if a user creates a record and quickly updates it, two Ajax requests are sent simultaneously - a POST and a PUT. How ...

Loading templates dynamically within ng-repeat is a powerful feature that enhances the flexibility and

I need help loading a template dynamically while using an ng-repeat: <ul> <li ng-repeat="prop in entity" > <div ng-include src="prop.template"></div> </li> </ul> The value of prop.template is the URL of ...

HTML Error: The result is unspecified

I have written a function that is supposed to return 105; 6.5 and 110; 4.5, but instead it returns undefined: undefinedundefined: undefined. Can someone please advise me on what changes I need to make to get the correct results? I have heard about asynchro ...

Exporting modules from Node.js using Express framework is a common

Encountering an issue with this error message Error: app.get is not a function This section shows my configuration in config/express.js var express = require('express'); module.exports = function(){ var app = express(); app.set(&apo ...

AngularJS allows for the uploading of files in each row of a table

Currently, I have implemented a table where users can enter details in each row and view the corresponding image. This functionality has been achieved using AngularJS. Although I managed to get it working for the first row after much effort, I am now faced ...

Error encountered during Angular unit testing: Unable to read the 'id' property of a null value. (Jasmine, Karma)

I am currently working on writing unit tests for a specific component in my Angular application. The component uses a currentUser variable both in the component logic and the HTML template. I have hardcoded this variable by mocking it in every test using c ...

An issue occurred with a malformed JSON string when attempting to pass JSON data from AngularJS

I am facing an issue with passing a JSON string in an ajax request. Here is the code snippet: NewOrder = JSON.stringify (NewOrder); alert (NewOrder); var req = { url: '/cgi-bin/PlaceOrder.pl', method: 'POST&apo ...

Issues with Angular Form Submission within Ng-repeat

Hey there, I have a form nested inside a table row that is part of an ng-repeat loop. Inside this form, there is a number field and a button (a custom directive called "action"). When the button is clicked, I want the form to perform validation before subm ...

extract values from a JavaScript function on a website

Currently, I am facing a challenge in automatically retrieving elements from a webpage and I seem to be stuck on a few things. My approach involves looping through all classes named 'trList' using document.getElementsByClassName('trList&apo ...