Enhancing Donut Chart with d3.js

After working for several hours, I'm having trouble getting my d3.js donut graph to update with new data.

Here's my HTML:

  <body>
    <div id="pie"></div>
    <script src="pie.js"></script>
  </body>

And here's my JavaScript code:

var dataset = [40, 20];

var width = 460,
  height = 300,
  radius = Math.min(width, height) / 2;

var color = ['#000000', '#FFFFFF'];

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

function render() {
  var pie = d3.pie()
    .sort(null);

  var arc = d3.arc()
    .innerRadius(radius - 100)
    .outerRadius(radius - 50);

  var path = svg.selectAll("path")
    .data(pie(dataset))
    .enter().append("path")
    .attr("fill", function(d, i) { return color[i]; })
    .attr("d", arc);
}

render();

function update() {

  dataset[0] = 100;

  render();
}

Although the donut graph is drawn successfully, calling the update() function doesn't refresh the graph on screen with the updated dataset.

I've looked at examples of bar charts using enter, append, and exit methods, but I'm struggling to apply them in my case.

If anyone can provide some guidance, it would be greatly appreciated. Thank you!

Answer №1

It is important to note that simply updating the data will not automatically reflect changes in the chart. To update the chart itself, you need to establish an "update" selection.

Currently, you only have an "enter" selection:

var path = svg.selectAll("path")
    .data(pie(data)).enter().append("path")
    .attr("fill", function(d, i) { return color[i]; })
    .attr("d", arc);

Whenever the dataset is changed, no visible changes occur in the chart because the "enter" selection remains empty. You could try selecting something non-existent:

var path = svg.selectAll(".foo")

However, this solution is not ideal as it will result in multiple paths accumulating in your SVG.

The recommended approach is to create both an "enter" and an "update" selection:

//binding the data:
var path = svg.selectAll("path")
    .data(pie(data));

//creating the "enter" selection:
var pathEnter = path.enter().append("path")
    .attr("fill", function(d, i) { return color[i]; })
    .attr("d", arc);

//establishing the "update" selection:
var pathUpdate = path.attr("d", arc);

Refer to this demo:

var dataset = [40, 20];

var width = 300,
    height = 200,
    radius = 150;

var color = ['#222', '#EEE'];

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

function render(data) {
    var pie = d3.pie()
        .sort(null);

    var arc = d3.arc()
        .innerRadius(radius - 100)
        .outerRadius(radius - 50);

    var path = svg.selectAll("path")
        .data(pie(data));

    var pathEnter = path.enter().append("path")
        .attr("fill", function(d, i) {
            return color[i];
        })
        .attr("d", arc);

    var pathUpdate = path.attr("d", arc);


}

render(dataset);

setInterval(function() {
    update();
}, 2000);

function update() {

    dataset = [Math.random() * 50, Math.random() * 50];

    render(dataset);
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="pie"></div>

Answer №2

Find the GitHub repository for the d3 donut sanky chart here

https://i.stack.imgur.com/aEZ1x.png

[![The donut chart has been updated to display text in the center]

 const data = {
      'fleetView': [
        {
          'VesselName': 'MOL Emissary',
          'IMO': '07158',
          'QS': 'Good',
          'SeaState': 'Under Way using engine',
          'STW': '12.4/11.6',
          'DepPort': 'DK RNN',
          'ArrPort': 'DK RNN',
          'Course': '123',
          'Speed': '11.7 km',
          'CurrentDraught': '10 m',
          'Start': '2019-02-18T00:42:55Z',
          'End': '0001-01-01T00:00:00Z'
        },
        // Rest of the vessel data goes here
      ]
    };

    function groupingBy(data, groupby) {
      return _.groupBy(data, groupby);
    }

    // More functions and D3 code for visualizing the data

// Further javascript script and visualization details can be found <a href="https://i.stack.imgur.com/qfIS0.png" rel="nofollow noreferrer">here</a>. 

]2]2

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 script fails to work correctly when displaying the data

Last night, I finally cracked the code on how to transfer data from my form on the index page to the content page, and then display the results inside the content div back on the index page. However, a new challenge has emerged. My Javascript function (re ...

How to efficiently transfer data between PHP and Javascript using ajax?

Struggling greatly with the ajax function within the jQuery library. As a beginner in jQuery, ajax, and php, I am currently engaged in a school project that involves creating a game-like environment where a 10x10 table generates numbers, selects a cell aut ...

How can we use JavaScript to retrieve an element with custom styling?

I've encountered a strange issue with my script where it seems to stack up borders and display a 2px border instead of the intended 1px border when switching elements on click. Here is the link code I am using: <li ><a href="plumbing.php"&g ...

Using WebRTC on a shared hosting environment (with SSH access) without the need for nodejs, ideally implemented in PHP

As I was exploring ways to integrate webRTC into a website that I am creating on shared hosting, I stumbled upon this GitHub repository by nielsbaloe. It has been incredibly helpful in establishing a basic connection. This particular code snippet appears ...

Integrating jQuery into the functions.php file of a Wordpress

I have been using a jQuery script in Unbounce and now I want to implement it on my Wordpress page. I believe I will have to insert this into the child theme functions file, but I know it requires some PHP code as well. As I am still fairly new to this proc ...

Unable to display the complete JSON data using ng-repeat in AngularJS

Utilize ng-repeat to display data retrieved from a web service. Below is my controller JS (GetAllCtrl.js): https://i.stack.imgur.com/GAelG.jpg I have received JSON data: https://i.stack.imgur.com/0xkAU.jpg My goal now is to extract only company informati ...

Problem encountered with imaskJS in handling the formatting of data with forward slashes

After conducting tests on the frontend of the imask website at , it has been verified that utilizing a forward slash for date formatting results in the exclusion of the final digit of the date. Various attempts were made, including: IMask( field, ...

Troubleshooting the issue with Protractor/Jasmine test when browser.isElementPresent does not detect a class in the

As a newcomer to Jasmine testing, I've been facing some challenges while running my tests. Specifically, I have been struggling with my webdriver closing the browser before it can check the '.detailsColumn' element for expected results. Afte ...

Create dynamic HTML files using Express, EJS, and FS, and deliver them using Nginx as the server instead of relying

Imagine a scenario where we have a JSON object: [ { "id": 1, "title": "Title 1", "description": "Description 1" }, { "id": 2, "title": "Title 2", ...

Error: Attempting to access the 'firstChild' property of a null object when trying to display a street view panorama with Vue.js

Looking to integrate a street view panorama using the Google Maps API in my VueJS project. I followed the documentation provided by Google maps here, and here is the basic template: <div id="map"></div> <div id="pano"></div> Her ...

Can object-fit be preserved while applying a CSS transform?

Currently, I am developing a component that involves transitioning an image from a specific starting position and scale to an end position and scale in order to fill the screen. This transition is achieved through a CSS transform animation on translate and ...

Navigating through paginated data can be made easier by using Backbone.PageableCollection in conjunction with a personalized

I have developed an application that interacts with a database known as LeanCloud. Currently, I have configured a page to display all the users stored in the database. However, LeanCloud has a limitation where only 100 pieces of data can be retrieved per r ...

Is it possible to modify the object's key value when generating an array value with the map function in React?

I have the array object data stored in a variable called hi[0].child. hi[0].child = [ {code: "food", name: "burger"}, {code: "cloth", name: "outer"}, {code: "fruit", name: "apple"}, ] ...

How can we wrap the Vuex store within a Vue plugin's install function?

I developed a plugin that utilizes Vuex for state management. // plugin.js import Vuex from "vuex"; import store from "./store.js"; export default { install(Vue, options) { const storeInstance = new Vuex.Store(store); Vue.pr ...

The onclick event for a Bootstrap .btn-group checkbox functions correctly in JSFiddle, but encounters issues when tested

The toggle button group in the form below utilizes Bootstrap and checkboxes. I am looking to track click events on the checkbox inputs. <html> <head> <title>Example: Bootstrap toggle button group</title> <meta charset="UTF-8 ...

Unable to integrate a new third-party script into a Next.js application

In my attempt to integrate the following script, I have tried adding it first to _document.js, then to app.js, and finally to a specific page. <Script src="https://anywebsite.ai/chatbot/chatbot.js"></Script> <Script id=" ...

Trigger animation once you've scrolled past a designated point in the document

I created a count-up counter animation using JavaScript, but the issue is that the counter starts animating as soon as I refresh the page regardless of where I am on the page or if the counter is even visible. I would like the counter to only start workin ...

Setting up a custom function for the cancel button in Angular X-editable

Can this be done? I've got a code snippet that resembles the following: <div class="popover-wrapper"> <a class="glyphicon glyphicon-time" ng-if="activity.type === 'continuous'" ng-style=" { 'border': 'none', ...

Is there a simple method to automatically increase the version number of Mongoose documents with each update request?

I'm eager to utilize Mongooses document versioning feature with the "__v" key. Initially, I struggled with incrementing the version value until I learned that adding this.increment() when executing a query is necessary. Is there a method to have this ...

What is the best way to determine the total of values from user-input fields that are created dynamically

Scenario- A scenario where a parent component is able to create and delete input fields (child components) within an app by clicking buttons. The value of each input field is captured using v-model. Issue- The problem arises when a new input field is crea ...