I'm looking to customize my d3.js Bar Graph by changing the color of each bar individually and adding a Scale for them. How can I

I am currently working on constructing a graph that illustrates the data for the Amount of Resources utilized Per Project by creating a bar graph. I am aiming to customize the colors of the bars so that each one has its own unique color. Currently, the colors are set to scale between 2 shades of blue based on their length, but I would like each bar to be one of three specific colors. Additionally, I am exploring ways to incorporate a legend that explains the meaning behind each color used in the bar graph.

<!DOCTYPE html>
<html>
<head>
  <meta>
  <meta name="description" content="Creating Shapes with D3 - " />
  <meta charset="utf-8">
  <title>Resource Breakdown per Project</title>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

  <style type="text/css">
    h1 {
      font-size: 35px;
      color: darkgrey;
      font-family: Helvetica;
      border-bottom-width: 3px;
      border-bottom-style: dashed;
      border-bottom-color: black;
    }
    
    h2 {
      font-size: 20px;
      color: black;
      font-family: Helvetica;
      text-decoration: underline;
      margin-left: 350px;
      margin-top: 0px; 
    }

    .label {
      font-size: 20px;
      color: darkgrey;
      font-family: "Arial Black";
      border-bottom-width: 3px;
      border-bottom-style: dashed;
      border-bottom-color: black;
    }
  </style>
</head>

<body>
  <h1>Resources utilized per Project</h1>

  <p>Select Month:
    <select id="label-option">
      <option value="April">April</option>
      <option value="May">May</option>
      <option value="June">June</option>
      <option value="July">July</option>
      <option value="August">August</option>
      <option value="September">September</option>
    </select>
    <script type="text/javascript">
      var width = 800
      var height = 500
      var emptyVar = 0
      var dataArrayProjects = ['2G', 'An', 'At', 'Au', 'AW', 'Ch', 'CI', 'CN']
      var April = [0.35, 1.66, 3.04, 1.54, 3.45, 2.56, 2.29, 1.37]
      var May = [0.36, 1.69, 3.08, 1.54, 3.62, 2.61, 2.22, 1.44]
      var June = [0.34, 1.7, 3.08, 1.63, 3.66, 2.68, 2.24, 1.51]
      var July = [0.3, 1.72, 3.17, 1.67, 3.56, 2.56, 2.17, 1.44]
      var August = [0.28, 1.79, 3.18, 1.71, 3.62, 2.73, 2.26, 1.54]
      var September = [1.23, 1.74, 3.12, 1.61, 3.66, 2.71, 2.2, 1.48]

      d3.select("#label-option").on("change", change)

      function change() {
        var data = April;
        if (this.selectedIndex == 1){
          data = May;
        } else if (this.selectedIndex == 2){
          data = June;
        } else if (this.selectedIndex == 3){
          data = July;
        } else if (this.selectedIndex == 4){
          data = August;
        } else if (this.selectedIndex == 5){
          data = September;
        }
        canvas.selectAll("rect")
        .data(data)
        .attr("width", emptyVar)
        .attr("height", 50)
        .attr("fill", function(d) {
          return color(d)
        })
        .attr("y", function(d, i) {
          return i * 55
        })

       bars.transition()
        .duration(1500)
        .delay(200)
        .attr("width", function(d) {
          return widthScale(d);
        });

        texts = canvas.selectAll(".label")
        .data(data)
        .attr("x", function(d) {
          return widthScale(d) + 10;
        })
        .attr("fill", function(d) {
          return color(d)
        })
        .attr("y", function(d, i) {
          return (i * 55) + 25
        })
        .style("opacity", 0)
        .text(function(d, i) {
          return d;
        }) 

        texts.transition()
        .duration(2000)
        .delay(180)
        .style("opacity", 1)  
      }

      var widthScale = d3.scale.linear()
        .domain([0, 4])
        .range([0, width - 60]);

      var heightScale = d3.scale.ordinal()
        .domain(dataArrayProjects)
        .rangePoints([10, height - 85]);

      var color = d3.scale.linear()
        .domain([0, 4])
        .range(["#FF5733", "#33CDFF", "#3333FF"])

      var xAxis = d3.svg.axis()
        .ticks("30")
        .scale(widthScale);

      var yAxis = d3.svg.axis()
        .scale(heightScale)
        .orient("left");

      var canvas = d3.select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(40, 0)");

      var bars = canvas.selectAll("rect")
        .data(April)
        .enter()
        .append("rect")
        .attr("width", emptyVar)
        .attr("height", 50)
        .attr("fill", function(d) {
          return color(d)
        })
        .attr("y", function(d, i) {
          return i * 55
        })
        
      var texts = canvas.selectAll(".label")
        .data(April)
        .enter()
        .append("text")
        .attr("class", "label")
        .attr("x", function(d) {
          return widthScale(d) + 10;
        })
        .attr("fill", function(d) {
          return color(d)
        })
        .attr("y", function(d, i) {
          return (i * 55) + 25
        })
        .text(function(d, i) {
          return d;
        })
        .style("opacity", 0)

      canvas.append("g")
        .attr("transform", "translate(0, 430)")
        .attr("font-family", "Helvetica")
        .attr("font-size", "15px")
        .call(xAxis);

      canvas.append("g")
        .attr("font-family", "Helvetica")
        .attr("font-size", "15px")
        .style("fill", "black")
        .attr("class", "y axis")
        .call(yAxis);

      bars.transition()
        .duration(1500)
        .delay(200)
        .attr("width", function(d) {
          return widthScale(d);
        })

      texts.transition()
        .duration(2000)
        .delay(180)
        .style("opacity", 1)

      var yAxisLine = canvas.append("line")
                        .attr("x1", -3)
                        .attr("y1", 0)
                        .attr("x2", -3)
                        .attr("y2", 436)
                        .attr("stroke-width", 6)
                        .attr("stroke", "black");

    </script>
    <h2>Resources</h2>
</body>
</html>

Is there a way to individually set the color of each bar and create a legend using these distinctive colors?

Thank you in advance!

Answer №1

When it comes to changing colors, you've already set up a variable color that is used for filling bars.

Your current code looks like this:

var color = d3.scale.linear()
    .domain([0, 4])
    .range(["#000033", "#22cdff"])

Instead of that, consider initializing with some fixed colors like so:

var color = ["#000033", "#22cdff", "#010101"]

Adjust the code accordingly to use these fixed colors for bar fills:

var bars = canvas.selectAll("rect")
    .data(April)
    .enter()
    .append("rect")
    .attr("width", emptyVar)
    .attr("height", 50)
    .attr("fill", function(d, i) {
        return color[i%3] // selecting colors from the array
    })
    .attr("y", function(d, i) {
        return i * 55
    })

var texts = canvas.selectAll(".label")
    .data(April)
    .enter()
    .append("text")
    .attr("class", "label")
    .attr("x", function(d) {
        return widthScale(d) + 10;
    })
    .attr("fill", function(d, i) {
        return color[i%3] // selecting colors from the array
    })
    .attr("y", function(d, i) {
        return (i * 55) + 25
    })
    .text(function(d, i) {
        return d;
    })
    .style("opacity", 0)

The colors will now be picked from the specified color array.

As for legends, there are various plugins and codes available. You can check out one of my answers for reference.

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

Users are reporting a problem with the PrimeNG confirmation dialog where it becomes unresponsive and locks up the screen

Previously functioning code seems to have been affected by an update to PrimeNG. The confirmation dialog that was once usable is now hidden behind a gray click-mask, rendering everything on the screen unclickable: The HTML structure for these two dialogs ...

What is the best way to position the header at the top and the footer at the bottom of the page, with the main content in between using

Recently, I started using Bootstrap and incorporated Bootstrap 5.3 into this HTML page. My goal is to align the header at the top, footer at the bottom, and adjust the size of the main content in between. Here's the code I attempted: <!DOCTYPE html ...

Using a custom jQuery function within an Angular component class

I have a custom query function that I wrote in a JavaScript file located under the source folder (/src/assets/inlineedit.js) of my Angular application. Here is the content of the file: $.fn.inlineEdit = function(replaceWith, connectWith) { $(this).ho ...

Is there a way to customize the cursor of the webkit resizer (pulltab)?

I'm having difficulty implementing a custom cursor on my webkit pulltab. While I am able to change other properties like background color, the CSS "cursor" property remains unchangeable: #sessionbuilder::-webkit-resizer { background: #000; cursor ...

Bootstrap Toggle Button with Dropdown Menu

I have a button-group with font awesome icons and a dropdown on one of them, as illustrated in the example below. I am trying to toggle the button status, but for some reason, the 'active' class is automatically removed on mouseout. It seems to ...

Tips for fixing the issue of "module ./response not found" in Node.js Express

Whenever I execute the command $ npm start this error message appears > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8feefcfce6e8e1e2eae1fbbccfbea1bfa1bf">[email protected]</a> start > nodemon server.js ...

Terminating a client connection in Node.js using socket.io

What is the best way to terminate the socket connection on the client side? I am currently utilizing: socket.io 0.9 node.js 0.10.15 express 3.3.4 For example, when calling localhost/test -- server side var test = io .of('/test') .on(&apos ...

Showing events from MySQL database on Vue.js Fullcalendar

I am trying to fetch events from my MySQL database and pass them to my Vue component to be displayed on the FullCalendar. However, the event array is being populated with a full HTML document. Below is my EventController: public function getEvents() { ...

Can CSS be used to generate these shadows?

Check out this image I made showcasing a board with an elongated shadow cast behind it. The intention is to emulate the look of the board leaning against a wall, resulting in a triangular shadow on either side. I'm curious if it's achievable to ...

What are the benefits of incorporating CSS into a CSS block rather than utilizing inline output with HtmlHelper in CakePHP?

Just a few days ago, I embarked on the journey of learning CakePHP through their blog tutorial. Now, I am diving into writing my own small project to gain hands-on experience with the framework. After going through their documentation, I discovered two ...

Infinite loop triggered by jQuery dropdown menu on page resize was causing an issue

I have been working on developing a navigation menu for a website that displays as a horizontal bar on larger screens, but transforms into a jQuery dropdown menu when the window width is less than 980px. During initial page load with a window width below ...

The jQuery show/hide functionality is malfunctioning

In my PHP code, I have the following loop: foreach ($sid as $key => $value) { $sql = " a sql query "; $vehicle->rowQuery($sql); $numRows = $vehicle->rows; while ( $data = $vehicle->result->fetch_assoc()) { $ ...

Issue with Discord.js (14.1) - Message Handling Unresponsive

After developing a sizable Discord Bot in Python, I decided to expand my skills and start learning JS. Despite thoroughly studying the documentation and comparing with my original Python Bot regarding intents, I am facing difficulties getting the message ...

The node.js API request is experiencing a unresponsive state

As a newcomer to the world of JavaScript, I am currently learning the basics of Node.js. One task I'm working on involves retrieving a contact from my mongoDB and creating a GET method to return it. Sounds simple, right? Below is the router method I ...

Arrange divs adjacent to each other without any gaps in between

My HTML code includes elements from Twitter Bootstrap and AngularJS framework. <div class="item item-custom-first"> <select class="form-control" style="display:inline; float:right" ng-model="requestdata.units ...

PHP and issues with search functionality

I am currently working on developing a search function to retrieve and display data from a MySQL database based on user selection. However, I encountered an error that I am not sure how to resolve. Can anyone provide assistance? I am fairly new to PHP. The ...

Update each number in an array by appending a string within a table in an Angular component, rather than the

I have created a function that decides on a comment based on the result number added to an array and displays it in a table. However, calling this function within the template is causing a performance slowdown. Is there a way to achieve the same outcome w ...

Triggering a dynamically created event with the onchange event

I'm currently working on creating an input type file, and here is the code I have: var element = document.createElement("INPUT"); element.type = "file"; element.id = "element" + i; $("#media").append("<br>"); $("#media").append("<br>"); $ ...

After refreshing the page, the ngRoute white page is displayed

I've encountered an issue with my Angular website. I built it using ngRoute, but when I click on a link, a white page appears. Only after refreshing the page does the content actually show up. Even in the browser's DevTools, you can see the html ...

Issues with integrating chart.js in Laravel 7: Element #app not found?

Currently, I am utilizing chart.js to display the statistics of reviews and messages for a user. However, I have encountered issues with the scripts. While the stats are functioning correctly, an error message stating Cannot find element: #app is appearing ...