Donut visualization within a Sankey diagram using D3 JS

Looking to enhance my D3 Js Sankey diagram by adding a donut chart around the company circles. The donut chart will display two values, numsms and nummid, within the company node. Below is an example of what I am trying to achieve:

However, I've been struggling to implement the donut chart around the company circles. Most examples I found show donut charts as separate SVG elements.

Here is a snippet of my code for the circles:

svg.selectAll(".node.circle")
        .append("circle")
        .attr("r", function(d) {
            if(d.node.indexOf("company-") > -1) {
                return company_circle_size(d);
            } else {
                return page_circle_size(d);
            }
        })
        // More circle styling and attributes

To target the company nodes, I update the class names in a loop:

$(selector).attr("class", "node company")

I believe the code snippet below should be placed within this section to create the donut chart around the company nodes:

svg.selectAll('.company').each(function(companyNode) {
        var values = [[companyNode.numsms, companyNode.nummid]];
        var total = companyNode.numsms + companyNode.nummid;

        if(total > 0) {
            // create donut chart
        }
    });

Answer №1

To add a div to a node, you can use foreignObject. Inside that div, include your values for an inline jQuery sparkline chart, such as a line or pie chart. Make sure to adjust the transparency of the div so it doesn't obstruct the diagram. Additionally, update the original sankey data array with your values (source, target, value, numsms, numid) and then reference them when appending with d.numsms.

// For sparkline plugin and setup, refer to http://omnipotent.net/jquery.sparkline/#s-docs
// Here is an example setup, check out the provided fiddle for more details

node.append("foreignObject")
.attr("width", sankey.nodeWidth()*2)
.attr("height", function(d) { return d.dy/2 })
.attr("transform", function(d) { return "translate(" + (d.x+20) + "," + (d.y+10) + ")"; })
.append("xhtml:body")
.style("font", "14px 'Helvetica Neue'")
.html("<div>Inline Sparkline: <span class='inlinesparkline'>1,4,4,7,5,9,10</span></div>");

After adding the div to each node, activate the plugin to display the inline charts.

$('.inlinesparkline').sparkline(); 

Take a look at the provided fiddle. Although it's not a sankey, it demonstrates how to use foreignObject.

Explore a d3.js diagram with inline charts!

I hope this explanation is helpful.

Answer №2

Finally circling back to address this query.

Check out this example where a sankey diagram is combined with a donut chart. Please note that this example is not tailored to your specific data, it serves as a generic representation.

// If there is no pie data, use rects as usual
node.filter(function(d){
    return !d.pieData;
  })
  .append("rect")
  .attr("height", function(d) {
    return d.dy;
  })
  .attr("width", sankey.nodeWidth())
  .style("fill", function(d) {
    return d.color = color(d.name.replace(/ .*/, ""));
  })
  .style("stroke", function(d) {
    return d3.rgb(d.color).darker(2);
  })
  .append("title")
  .text(function(d) {
    return d.name + "\n" + format(d.value);
  });

// Establish donut chart components
var pColor = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

var arc = d3.svg.arc()
    .outerRadius(50)
    .innerRadius(20);

var pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { return d.value; });

// If there is pie data, render the donut chart
var g = node.filter(function(d){
    return d.pieData;
  })
  .append("g")
  .attr('transform', function(d,i){
     return 'translate('+d.dx/2+','+d.dy/2+')'; // correct positioning
  })
  .attr("class","donut")
  .selectAll(".arc")
  .data(function(d){
    return pie(d.pieData); // nested selection to assign data
  })
  .enter().append("g")
  .attr("class", "arc");

g.append("path")
  .attr("d", arc)
  .style("fill", function(d,i) { return color(i); });

Answer №3

You can find the Sankey and Piechart implementation by visiting the following link: (please note that the pie-chart is in a static div, remember to move it above your node when you use it)

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

Leveraging Environment Variables in Separate JavaScript Files within a Node Express Application

After trying various methods and searching extensively online, I am struggling to use environment variables in a separate JavaScript file within an Express App. My Setup: In my Express app, I have an index.js file that serves an HTML page with associated ...

Problem with Express.js serving dynamically generated index.html page

Currently, I'm immersing myself in a practice project to grasp the concepts of express and webpack with react and react router. My goal is to make sure all server requests are directed to index.html to avoid encountering "Cannot GET" errors when navig ...

The setAttribute method does not function with getElementByClass()

Can someone please help me understand why this code is not working for me: document.getElementByClass('home1').setAttribute('style', 'background-image:url(img/red_menu.PNG);'); I have confirmed that I do indeed have an eleme ...

Encountering issues while running the npm build command due to exporting async functions in React

In my React project, I am utilizing async functions and have created a file named apiRequest.js structured like this: const axios = require('axios'); const serverURL = "http://localhost:8080" getInfo = async function ({email}) { try { r ...

Utilize a select box to toggle between enabling and disabling options

Could someone please help me with enabling and disabling a text field based on a select box option? I'm not sure if I have written the code correctly below. If there are any errors, please correct me. <body> <table width="500" border="1"> ...

Ensure that the view is only updated once the JSON has been completely received from the AJAX call in AngularJS

Just starting out with angularJS and still in the learning phase. I'm currently working on creating a navbar for the header that will fetch data from an ajax call. The issue I'm facing is that it displays {{obj.pageData}} until the data is fully ...

Activate browser scrollbar functionality

Below is the HTML code snippet: <html> <head> <style> #parent { position : absolute; width : 500px; height : 500px; } #top { position : absolute; width : 100%; height: 100%; z-index : 5; } #bottom { position : absolute; width : 100%; ...

Most effective method to verify if mutation observer meets specific criteria

I have set up a mutation observer to monitor changes in the page load. Specifically, I am interested in detecting the moment when a particular element is loaded or exists. This element can be identified by its classname, let's say it's called foo ...

Securing page access with a straightforward password protection using Flask

Looking for a straightforward way to add password protection to a Flask app site. I've explored options like flask_login, but they seem overly complex for my needs. I don't need high security or login sessions - just something like: "enter passw ...

following the history.back() function call, the subsequent codes are executed

<?php $ok_register = 0; if($ok_register != 1) { ?> <javascript type="text/javascript"> alert("1"); history.back(); </javascript> <?php } ?> <javascript type="text/javas ...

Why am I unable to access all elements within the map function?

Hey there, I have a function related query. Whenever I try to access my data, I can only reach the first index of each array. For instance, I have 5 different images of PlayStation, but on my webpage, I am only able to see one image. How can I resolve this ...

Counting the occurrence of a specific class within an element using jQuery

Within my table, each row is assigned one or more classes based on its region. This is the structure of my table: <table> <thead> <th>Title</th> <th>Name</th> </thead> <tbody> <tr class="emea ...

Track the loading time of a webpage and the time it takes to render all subelements of

For my project, I need to track page load times for each individual visitor. My idea is to embed a JavaScript snippet into the page in order to achieve this goal. However, the task is more complex than I anticipated because I also need to measure the respo ...

"Utilizing Jquery to extract data from a form field and combine it with a URL for maximum value

Today, I am delving into the world of jQuery for the first time and finding myself in need of some assistance with a particular problem. While this issue may seem trivial to experienced individuals, it is posing quite a challenge for me. The dilemma lies ...

Exploring the world of web programming

Looking for top-notch resources to learn about JavaScript, AJAX, CodeIgniter and Smarty. Any recommendations? ...

Converting a stringified array object to an object using Expressjs

When working with Angular, I am sending stringified data using FormData. Here is an example: this.formData.append('data', JSON.stringify(this.collections)) Now my challenge is converting this string back to an object in my Express backend. The d ...

Trigger .gif on hover using ng-repeat in AngularJS

Many solutions to this problem involve using jQuery, such as the following examples: Stop a gif animation onload, on mouseover start the activation and Animating a gif on hover. However, I'm interested in achieving the same functionality using Angular ...

Tips for adapting the position of a floating div according to its height and environment

Important Note: The code below utilizes the rubuxa plugin for handling JS sortables. Javascript: function querySelector(expr){return document.querySelector(expr)} var container = querySelector('.ITEST'); var sortable = Sortable.create(container, ...

Dynamic background image that fills the entire webpage, adjusts to different screen sizes, and changes randomly

Currently, I am working on designing a web page with a dynamic background image that adjusts responsively in the browser without distortion. The challenge is to randomly select an image from an array using jQuery. Unfortunately, my knowledge of jQuery is ...

What is the formula for determining the size of an image using JavaScript, jQuery, or Java?

I'm looking to determine the dimensions of an image. I have both the image src and base64 data available. My goal is to display the current size of the image. I am working with Java and JavaScript. Is there a way for me to calculate the image size usi ...