Developing a complex pie chart with multiple layers using D3

Is it possible to create a multi-layer pie chart using d3.js with the following design?

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

In this pie chart, each section may or may not have an inner subsection. If there is a subsection, it should be displayed in a darker color compared to the outer section as shown in the image.

I've been searching for ways to create a multilayer pie chart but so far I could only achieve this:

http://jsfiddle.net/ZpQ3x/

Below is the corresponding JavaScript code:


var dataset = {
  final: [7000],
  process: [1000, 1000, 1000, 7000],
  initial: [10000],
};

var width = 660,
    height = 500,
    cwidth = 75;

var color = d3.scale.category20();

var pie = d3.layout.pie()
    .sort(null);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("class","wrapper")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")

var gs = svg.selectAll("g.wrapper").data(d3.values(dataset)).enter()
        .append("g")
        .attr("id",function(d,i){
            return Object.keys(dataset)[i];
        });

var gsLabels = svg.selectAll("g.wrapper").data(d3.values(dataset)).enter()
        .append("g")
        .attr("id",function(d,i){
            return "label_" + Object.keys(dataset)[i];
        });

var count = 0;
var path = gs.selectAll("path")
    .data(function(d) { return pie(d); })
  .enter().append("path")
    .attr("fill", function(d, i) { return color(i); })
    .attr("d", function(d, i, j) { 
        d._tmp = d.endAngle;
        d.endAngle = d.startAngle;
        if(Object.keys(dataset)[j] === "final"){
            d.arc = d3.svg.arc().innerRadius(cwidth*j).outerRadius(cwidth*(j+1)); 
        }
        else{
            d.arc = d3.svg.arc().innerRadius(10+cwidth*j).outerRadius(cwidth*(j+1)); 
        }
        return d.arc(d);
        })
    .transition().delay(function(d, i, j) {
            return i * 500; 
    }).duration(500)
    .attrTween('d', function(d,x,y) {
       var i = d3.interpolate(d.startAngle, d._tmp);
       return function(t) {
           d.endAngle = i(t);
         return d.arc(d);
       }
    });

Your help is greatly appreciated.

Answer №1

I have converted your dataset into a single JSON format.

To ensure that the arrays x and x1 mentioned above are correlated, I structured the data set in the following way.

data = [{
    major: 100,//first element of array X
    minor: 70,//first element of array X1
    grp: 1//segment coloring identifier
}, {
    major: 100,
    minor: 30,
    grp: 2
}, {
    major: 100,
    minor: 50,
    grp: 3
}, {
    major: 140,
    minor: 70,
    grp: 4
}, {
    major: 80,
    minor: 10,
    grp: 5
}];

I created two arc functions for this purpose.

var arcMajor = d3.svg.arc()
    .outerRadius(function (d) {
    return radius - 10;
})
    .innerRadius(0);

var arcMinor = d3.svg.arc()
    .outerRadius(function (d) {
    return scale((d.data.major - d.data.minor));
})

The following code generates the paths.

//creating the major arc
g.append("path")
    .attr("d", function (d) {
    return arcMajor(d);
})
    .style("fill", function (d) {
    return d3.rgb(color(d.data.grp));
});

//creating the minor arcs
g.append("path")
    .attr("d", function (d) {
    return arcMinor(d);
})
    .style("fill", function (d) {
    return d3.rgb(color(d.data.grp)).darker(2);//making the inner path darker
});

View the working code here with explanatory comments

I trust this explanation is helpful!

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

The Axios request for the concatenated URL is failing to execute

Encountering an issue with Axios in node js. Here's the code snippet: let callResult = await axios.get(urlData, config) The configuration object used is as follows: let config = { headers: { 'X-Token': token } ...

Various Plus/Minus Containers

One issue I am facing is that when using multiple counters on the same page, my - and + buttons to decrease or increase the number in a text box do not function properly. The script provided below works for one counter. How can I modify this code so that ...

What is the best way to collaborate and distribute local npm packages within a shared repository across different teams?

Unique Scenario Imagine the structure of a folder as follows: /my-app /src /dist /some-library /src /dist package.json my-package.json Two npm packages are present: one for my-app and one for some-library. my-app relies on some-library. ...

Retrieving checkbox values from HTML and storing them in a temporary JavaScript/HTML variable

My form has multiple checkboxes all with the same id "cbna". When I submit the form, I want the JavaScript code to check if at least one checkbox is checked. If no checkbox is checked, an alert should appear. If a checkbox is checked, the value stored in ...

What could be causing the React.js axios data to display on the console but not on the screen?

I am currently working on a React Axios Project using data from . The characters data includes another API link, so I implemented an Axios loop to display the names of the characters. While I can see the characters' names in the console, they are not ...

Retrieving information from an AJAX callback

Is there a way to extract the URLs from PHP data? Here is an example script that may help you achieve this: PHP $query = 'SELECT * FROM picture LIMIT 3'; $result = mysql_query($query); while ($rec = mysql_fetch_array($result, MYSQL_ASSOC)) { ...

Disappear scrollbar when overlay is activated

How can I hide the scroll bar when an overlay is displayed on my page? .overlay{ display: none; opacity:0.8; background-color:#ccc; position:fixed; width:100%; height:10 ...

A pop-up appears, prompting me to redirect to an external URL when clicking on a link that opens in a new tab on my WordPress website

Seeking assistance in dealing with a popup that appears when trying to open a link redirected to an external URL. The popup prompts for permission to open the link in a new tab. Upon inspecting the Element, the code snippet below is revealed: <div cla ...

How can I show a loading screen while making a synchronous AJAX call in Chrome?

Is there any method to show a loading screen in Chrome while using async:false in an AJAX call? The use of setTimeout poses several challenges when making multiple synchronous AJAX calls within the setTimeout function. Additionally, the loading indicator ...

What is the most effective method for invoking an inherited method (via 'props') in ReactJS?

From my understanding, there are two primary methods for calling an inherited method on ReactJS, but I am unsure which one to use or what the best practice is. class ParentCont extends React.Component { constructor(props) { super(props); t ...

Disabling past dates in a React JS application with a React date picker

Can someone help me figure out how to prevent selecting past times in React JS? Here is the code snippet: import DatePicker from "react-datepicker"; import setHours from "date-fns/setHours"; import setMinutes from "date-fns/setMi ...

What is the best method for waiting on a JavaScript function to provide a response utilizing the Chrome.storage API?

I am attempting to utilize the given code for managing name value pairs in a Chrome Extension. if (!this.Chrome_getValue || (this.Chrome_getValue.toString && this.Chrome_getValue.toString().indexOf("not supported") > -1)) { this.Chrome_getV ...

Tips for incorporating Bootstrap classes into a React project, setting the className attribute to an empty string

After setting up Bootstrap and Create-React-App using npm on my local machine, I proceeded to create a new React app. The first component I worked on was counter.jsx: import React, { Component } from 'react'; class Counter extends Component { ...

Adding a static global constant in webpack dynamically

I'm facing a challenge with adding a global constant to my project using webpack.DefinePlugin. I've successfully added one in the module.exports, but I struggle to do this conditionally. When I declare and use '__VERSION__' in my module ...

Exploring the $scope variable in AngularJS using JavaScript

How can I assign values to $scope.dragged and $scope.dropped in a JavaScript function? function drag(e){ e.dataTransfer.setData("text/html", e.target.id); console.log(e.target.id); $scope.dragged = e.target.className; } function drop(e){ ...

Ways to eliminate the worldwide model in SAPUI5

I've been attempting to break down the global model without success. I have a filter button that's set up like this: navToSecond : function (oEvent){ var oObject = this.getView().byId("inp").getValue(); sap.ui.getCore().setModel( ...

Exploring Angular 9: Harnessing the Power of Fork Join with an Array of

I have a challenge where I need to send multiple API requests to an endpoint by iterating over an array of values To handle this, I decided to use rxjs library and specifically the forkJoin method //array to keep observables propOb: Observable<any>[ ...

Exploring the art of div transitions and animations using React and Tailwind CSS

I successfully implemented the sidebar to appear upon clicking the hamburger icon with a transition. However, I am now facing the challenge of triggering the transition when the close button is clicked instead. I have attempted using conditional operations ...

What causes certain webpack / Babel ES6 imports without a specified extension to resolve as "undefined"?

When I try to import certain ES6 files (such as .js, .jsx, .ts, .tsx) using the syntax import ComponentName from './folder/ComponentName'; (without extension), they end up resolving as undefined. This occurs even though there are no errors from W ...

fullpage.js: the content exceeds the height limit

I am currently working on customizing the jquery script fullpage.js for a website built on the French CMS "SPIP" (). This script is used to create a one-page website with both horizontal and vertical navigation. However, I have encountered an issue with ...