Enhance D3 Version 6 Stacked Bar Chart with Spacing and Interactive Features

My bar chart lacks the spacing between bars that I intended to achieve, and the interactive tooltip doesn't show up when hovering over the bars. I could use some assistance with this. The purpose is to display the value of a specific color when hovering over it.

Codepen link: codepen.io/irwinmier96/pen/qBaKmma

Below is my code:

<!DOCTYPE html>
<html lang="en">

<head>

<meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Communities Fighting Covid</title>

  <!-- Bootstrap core CSS -->
  <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">

  <!-- Custom styles for this template -->
  <link href="css/modern-business.css" rel="stylesheet">

  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>

</head>

<body>
<script>
        var margin = {top: 20, right: 160, bottom: 35, left: 30};

        var width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

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

        /* Data in strings like it would be if imported from a csv */

        var data = [
        { race: "A", positive: "60", total: "600"},
        { race: "C", positive: "58", total: "500"},
        { race: "D", positive: "85", total: "600"},
        { race: "E", positive: "56", total: "500"},
        { race: "F", positive: "89", total: "700"},
        { race: "G", positive: "62", total: "400"}
        ];

        // Transpose the data into layers
        ...

        </script>

</body>

Answer №1

One clever technique for adjusting spacing involves adding a slight adjustment factor:

.attr("x", function(d) { return x(d.data.race) + 2; }) //<- shift right by two pixels to maintain center alignment
.attr("y", function(d) { return y(d[0] + d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[0] + d[1]); })
.attr("width", x.bandwidth() - 4) //<- reduce width by 4

If you're utilizing a code snippet from an older version of d3 for your tooltip, it's worth noting that in d3.js version 6, the callback was updated to provide the event object where you can access the cursor position:

.on("mousemove", function(e,d) {
    var xPosition = e.offsetX - margin.left + 10;
    var yPosition = e.offsetY - margin.top - 10;
    tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
    tooltip.select("text").text(d[1]);
});

Functional code example:

<!DOCTYPE html>
<html lang="en">

<head>

<meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>Communities Fighting Covid</title>

  <!-- Bootstrap core CSS -->
  <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">

  <!-- Custom styles for this template -->
  <link href="css/modern-business.css" rel="stylesheet">

  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>

</head>

<body>
<script>
        var margin = {top: 20, right: 160, bottom: 35, left: 30};

        var width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

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

        /* Data provided as strings, mimicking csv import */

       ...
  
        var tooltip = svg.append("g")
        .attr("class", "tooltip")
        .style("display", "none");
            
        tooltip.append("rect")
        .attr("width", 30)
        .attr("height", 20)
        .attr("fill", "white")
        .style("opacity", 0.5);

        tooltip.append("text")
        .attr("x", 15)
        .attr("dy", "1.2em")
        .style("text-anchor", "middle")
        .attr("font-size", "12px")
        .attr("font-weight", "bold")
        .attr("fill", "black")

        </script>

</body>

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

Angular filter within a nested ng-repeat loop

I've encountered an issue with nested filtering in Angular, where two filters are dependent on each other. What I'm trying to achieve is the following: <div ng-repeat="g in groups | filter:groupFilter"> ... <tr ng-repeat="c in g.co ...

Passing request parameters through an HTML form in Spring MVC

Currently diving into Spring MVC and exploring web development. Here is a method from my Controller: @GetMapping("/deleteCar") public String deleteCar(@RequestParam("carId") int carid) { carService.deleteCar(carid); return "redirect:/car/cars"; } ...

MongoSearch: A Geo-Targeted Search Engine tailored to your needs

For my new app project, I am using MongoDB, Express, JS, and Node to create a platform similar to Yelp. After some research, I discovered how to search for multiple fields within a campus schema (including campuses, restaurants, barbershops, and names). No ...

Undefined type in JavaScript

Below is the JavaScript code snippet I have written. function bar() { var x = "Amy"; x = parseInt(x); console.log(x); if (isNaN(x)) { console.log("Your entry is not a number"); } else { if (typeof (x) === "number") { console.log("number" ...

How to utilize DefinePlugin in Webpack to pass NODE_ENV value

I am attempting to incorporate the NODE_ENV value into my code utilizing webpack through the use of DefinePlugin. I have reviewed a similar inquiry on Stack Overflow, but I am still encountering issues. Here is the configuration I am working with: In pac ...

A step-by-step guide on modifying the box-shadow color using jquery

I have developed some JavaScript code that adjusts the box-shadow of buttons to be a darker version of their background color. This allows users to dynamically change the button background colors. The current code successfully changes the box shadow based ...

Seeking a quick conversion method for transforming x or x[] into x[] in a single line of code

Is there a concise TypeScript one-liner that can replace the arrayOrMemberToArray function below? function arrayOrMemberToArray<T>(input: T | T[]): T[] { if(Arrary.isArray(input)) return input return [input] } Trying to cram this logic into a te ...

Managing errors in React Router on the server-side

I am currently working on an isomorphic application using react-router and express. My goal is to implement custom error pages that will be displayed in case of server-side errors, rendering errors, or when a page is not found. However, I am facing difficu ...

Issue with Bootstrap 4 Navbar collapsing and not expanding again

Help needed! My navigation bar collapses when the window is resized, but clicking on the hamburger icon does not open it back up. I have included my code below. Can someone please provide guidance on how to expand the collapsed navbar? <html lang=&quo ...

Transmitting HTTP headers using Node.js

Within my Node JS Express application, I have an API endpoint called 'download' that returns a buffer to the calling application along with a header named 'status', which is a Javascript object. The response from Node sends the buffer ...

Firefox throwing XML parsing error when SVG is encoded as data URI

Check out my codepen demo showcasing the issue: codepen.io/acusti/pen/mJmVRy Encountering an error when trying to load svg content in Firefox: XML Parsing Error: unclosed token Location: data:image/svg+xml;utf8,<svg%20viewBox='0%200%20120%2 ...

Creating a Duplicate of the Higher Lower Challenge Game

To enhance my comprehension of React, I am constructing a replica of the website: Instead of utilizing Google searches, I opted for a dataset containing Premier League stadiums and their capacities. Up to this point, I have crafted the subsequent script: ...

CSS tip: Create a trendy design by adding a slanted border to the last

I need help creating a unique menu list with a white border design. The borders should all be straight by default, except for the last border which must be slanted. ul { background-color: #183650; } li { list-style: none; display: inline-block; b ...

The layout of the table is not formatted in a single continuous line

I recently implemented the material-ui table and noticed that the header has a multiline break space. I am looking for a way to make it display in a single line instead. Is there any solution for achieving this using material UI or CSS? Feel free to chec ...

What steps can be taken to create an electron menu for easily conducting a general search within the current window?

I am searching for a solution to create an electron menu that includes the label "Find..." and performs a general search within the current browser window. While I was successful in adding the option, I am struggling to figure out how to access the browser ...

Produced inputs and preset values

I have a question regarding the use of generated input elements in my App's form. I want to keep it as simple as possible, which is why I am using native form reset for these elements. It appears that the 'default value' becomes bound to th ...

Vue Router does not enforce redirects

I am currently facing an issue where the requireAuth() function is being called repeatedly, causing a loop. I only want to display pages when the user is logged in. This is the code snippet I am using: // Routes const routes = [ { path: &apos ...

Encountering an issue when attempting to update by pressing the button

I am encountering a challenge in my Vue application that involves inserting, updating, and deleting posts using MongoDB. Specifically, I am facing an issue with the update function. Whenever I attempt to update a post by clicking the corresponding button, ...

When the mouse hovers over, alter the background color with React

Currently attempting to adjust the background color of a Grid section when the mouse enters. I've made some progress, but now I seem to be stuck. My current approach involves calling a function to update the background color on mouse enter. const [isS ...

How can I securely store passwords for web scraping with Puppeteer to ensure maximum safety?

Looking for advice on scraping a website that requires login. The current code saves username and password in a config JSON file, which poses a security risk if the file is accessed by unauthorized individuals. Is there a more secure method, such as encr ...