Enhancing d3 pie chart with additional information when hovering over slices

I'm currently working on finding a way to display additional text on a pie chart using mouseover in addition to just the data bound to the pie. Here is the code I have implemented:

function Pie(value,names){

svg.selectAll("g.arc").remove()

var outerRadius = 100;
        var innerRadius = 0;
        var arc = d3.svg.arc()
                .innerRadius(innerRadius)
                .outerRadius(outerRadius);

    var pie = d3.layout.pie();
    var color = d3.scale.category10();
    var arcs = svg.selectAll("g.arc")
              .data(pie(value))
              .enter()
              .append("g")
              .attr("class", "arc")
              .attr("transform", "translate(950,80)");

    arcs.append("path")
            .attr("fill", function(d, i) {
                return color(i);
            })
            .attr("d", arc)
            .on("mouseover",function(d,i) {
             arcs.append("text")
                .attr("dy", ".5em")
                .style("text-anchor", "middle")
                .style("fill", function(d,i){return "black";})
                .text(d.data)
            })

            .on("mouseout", function(d) {

                arcs.select("text").remove();
            });}

The names array has the same length as the value array, which is provided to the pie. I was hoping that replacing the initial mouseover with something like this would solve it:

.on("mouseover",function(d,i) {
             arcs.append("text")
                .attr("dy", ".5em")
                .style("text-anchor", "middle")
                .style("fill", function(d,i){return "black";})
                .text(function(d,i){return (d.data +" " + names[i]);)
            })

However, instead of displaying the desired text, it simply stacks all elements of the values array and shows the last element of the names array. It appears that i always corresponds to the last index in this scenario. How can I address this issue? Is there an alternate method for achieving the intended text display? Your assistance is greatly appreciated.

Answer №1

Initially, the variable arcs is a d3 selection that is bound to data and represents all arcs in the pie chart. Therefore, when you use arcs.append, you are actually appending a text element for each arc of your pie chart. To correct this, consider updating your code snippet as follows:

svg.append('text')
  ...

Secondly, within this line of code:

.text(function(d,i){return (d.data +" " + names[i]);)

The variables d and i represent the data and index respectively in the mouseover function. Wrapping them in an additional function is unnecessary, so you should modify it to:

.text(d.data +" " + names[i]);

Below is a complete example provided for reference:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  body {
    font: 10px sans-serif;
  }
  
  .arc path {
    stroke: #fff;
  }
</style>

<body>
  <script src="//d3js.org/d3.v3.min.js"></script>
  <script>
    var width = 960,
      height = 500,
      radius = Math.min(width, height) / 2;

    var color = d3.scale.category10();

    var arc = d3.svg.arc()
      .outerRadius(radius - 10)
      .innerRadius(0);

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

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

    var data = [{
      value: Math.random(),
    }, {
      value: Math.random(),
    }, {
      value: Math.random(),
    }, {
      value: Math.random(),
    }, {
      value: Math.random(),
    }]
    
    var names = ["A","B","C","D","E"];

    var arcs = svg.selectAll(".arc")
      .data(pie(data))
      .enter().append("g")
      .attr("class", "arc");

    arcs.append("path")
      .attr("d", arc)
      .style("fill", function(d,i) {
        return color(i);
      })
      .on("mouseover", function(d, i) {
          console.log(d);
          svg.append("text")
            .attr("dy", ".5em")
            .style("text-anchor", "middle")
            .style("font-size", 45)
            .attr("class","label")
            .style("fill", function(d,i){return "black";})
            .text(names[i]);
          
      })
      .on("mouseout", function(d) {
        svg.select(".label").remove();
      });
    
  </script>

</body>

</html>

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

Changing the default yarn registry for a specific project

Typically, I fetch packages from the internal server by using the command: yarn config set registry http://custom-packages-server.com However, for a new project, I want to switch back to the default registry without affecting other projects. If I try cha ...

How can we use jQuery to animate scrolling down to a specific <div> when clicking on a link in one HTML page and then navigating to another HTML page?

I'm currently working on creating a website for my friend who is a massage therapist. Utilizing a bootstrap dropdown menu, I have added links to different treatments that direct to the treatment.html from the index.html page. Is there a way to creat ...

What is the hostname that npm install directs to?

My task is to set up multiple Node.js packages using npm on a standalone server that does not have direct internet access. I am able to specify an IP Address and port for access. When executing 'npm install' from the command line, where can I f ...

Keep track of the user's email address as they complete the form

I currently use a Google Form to gather information from employees who work in remote locations Emp No * Punch * Customer details / mode or travel All the data collected is stored in a Google spreadsheet structured as follows: Timestamp Emp No Punch ...

Error in Node.js: [Error: Query parameter should not be empty]

I've been recently focusing on a project that involves sending the required name to my profile.js file using a POST request. However, whenever I try to access console.log(req.body.bookName) (as the data being sent is named bookName), it shows an error ...

Tips for altering the appearance of a button when moving to a related page

I have a master page with four buttons that have a mouse hover CSS property. Each button's corresponding response page is defined on the same master page. Now, I want to change the button style when the user is on the corresponding page. How can this ...

My controller in AngularJS is having trouble fetching the latest values of the $scope variables

In my code, I've included the relevant snippet below. The base angularJS seems to be functioning properly as the HTML document doesn't display {{}} variables but instead remains blank. I suspect that this is due to the variables receiving a null ...

Creating an expandable discussion area (part II)

After checking out this query that was posted earlier, I am interested in implementing a similar feature using AJAX to load the comment box without having to refresh the entire page. My platform of choice is Google App Engine with Python as the primary lan ...

Submitting forms from a different router in React can pose a unique challenge

As a beginner in React, I am working on creating a simple meal app. In my App component, I am fetching meal data from an api and allowing users to click on a meal for more details. However, I am facing an issue where searching for a new meal on the detail ...

Tips for updating JS and CSS links for static site deployment

As I develop my static site using HTML files served from a simple web server, I want to use local, non-minified versions of Javascript code and CSS files. However, when it comes time to deploy the site, I would like to refer to minified versions of these s ...

Sort choices based on the optgroup category label text

I want to create a system where the user can select a game from one dropdown menu and then see only the consoles that game is available on in another dropdown menu. For example, if the user selects a game like Forza Horizon which is available on multiple c ...

The PHP Ajax code runs a for loop twice, but the data is only stored once during its execution

<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> </head> <body onload="searchVideo();"> <script> var data_length = 2; for(var i=0; i<data_length; i+ ...

There seems to be a hiccup in the system as we are unable

Upon visiting the URL address http://localhost:3000/test, I intend to load a log message. However, an error is returned stating "Cannot GET /test". Below is the code snippet in question: import express from 'express'; import React from 'rea ...

Utilizing jQuery to compute dynamic fields depending on selection in a dropdown menu

Creating a Ruby app for tracking bets, I have designed a small form that captures various details including date and match. However, the most crucial components of this form are the "stake" and "odd" text fields. To enhance user experience, I have incorpor ...

JavaScript makes it simple to display student names based on their ID numbers

Here is my JavaScript code: <script language="Javascript"> var data = { 7: "Jack Black", 8: "John Smith" }; var id = document.getElementById("id"), emp = document.getElementById("name"); id.addEventListener("keyup", function() { emp.value ...

How to access webpack's require.context feature on the development server

In my webpack development configuration, I have set up a mocked backend using Express. Following an example from the DevServer Docs, my setup looks something like this: module.exports = { // ... devServer: { setupMiddlewares: (middlewares, devServe ...

JS: Discovering an element's screen position consistently across various computers

I am currently working with a matrix of size 13 x 20, where each cell contains a number ranging from 0 to 300, representing different tiles to build a map. In addition, there is a "hero" character - a movable image. Pressing an arrow key will move the her ...

Configuring the Port for NodeJS Express App on Heroku

Currently, I am in the process of hosting my website on Heroku and configuring everything to ensure my app is up and running smoothly. However, each time I attempt to submit the form, undefined errors occur. For more details on the Undefined Errors and Co ...

Preventing form submission with JavaScript by implementing multiple validation checks

Preventing a form from submitting when validation returns false is possible. Here's an example: <form name="registration" action="registration.php" onsubmit="return validate()"> <!-- some inputs like: --> <input type="text" id="us ...

Stopping Angular.js $http requests within a bind() event

As stated in this GitHub issue Is it expected to work like this? el.bind('keyup', function() { var canceler = $q.defer(); $http.post('/api', data, {timeout: canceler.promise}).success(success); canceler.resolve(); } ...