Home > Blockchain >  D3 change the background color of an element based on it's data value
D3 change the background color of an element based on it's data value

Time:09-18

I am working with D3js and I have this project where I have to sort some data with data chart and stuff. What I want to do is colorize the charts background based on their data value. For example, the more points a student has, the darker his chart will be. Here is what I want to do and here is what I have.

Lets say my data array is:

var students =
 {"name":"John","value":"9"},
{"name":"Jack" ,"value":"10"},
{"name":"Peter","value":"3"}];

And this is my script.js class which I use to draw my charts:

var x = d3.scale.linear()
    .range([0, width])
    .domain([0, d3.max(students, function (d) {
        return d.value;
    })]);

var y = d3.scale.ordinal()
    .rangeRoundBands([height, 0], .1)
    .domain(students.map(function (d) {
        return d.name;
    }));

//make y axis to show bar names
var yAxis = d3.svg.axis()
    .scale(y)
    //no tick marks
    .tickSize(0)
    .orient("left");

var gy = svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)

var bars = svg.selectAll(".bar")
    .data(students)
    .enter()
    .append("g")

//append rects
bars.append("rect")
    .attr("class", "bar")
    .attr("y", function (d) {
        return y(d.name);
    })
    .attr("height", y.rangeBand())
    .attr("x", 0)
    .attr("width", function (d) {
        return x(d.value);
    });

Is there anyway I can do this, maybe by "if(students.value<=10) bar.style.backgroundcolor("red") else if(students.value <=5)bar.style.backgroundcolor("pink")

CodePudding user response:

You can create a color scale and use it to set the fill attribute for the rectangles. In the example below, I use a sequential scale for this.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="https://d3js.org/d3.v7.js"></script>
</head>

<body>
    <div id="chart"></div>

    <script>
      // chart data

      const data = [
        {name: 'John', value: 80},
        {name: 'Jane', value: 85},
        {name: 'Albert', value: 56},
        {name: 'Ramson', value: 90},
        {name: 'Rick', value: 70},
        {name: 'Karen', value: 30},
        {name: 'Jaden', value: 40},
        {name: 'Gustav', value: 15},
        {name: 'Nathan', value: 95},
      ].sort((a, b) => d3.descending(a.value, b.value));

      // dimensions and margins

      const margin = { top: 10, bottom: 30, left: 30, right: 10};

      const width = 500 - margin.left - margin.right;
      const height = 200 - margin.top - margin.bottom;

      const svg = d3.select('#chart')
        .append('svg')
          .attr('width', width   margin.left   margin.right)
          .attr('height', height   margin.top   margin.bottom);

      const g = svg.append('g')
          .attr('transform', `translate(${margin.left},${margin.top})`);

      // scales

      const x = d3.scaleBand()
          .domain(data.map(d => d.name))
          .range([0, width])
          .padding(0.15);

      const y = d3.scaleLinear()
          .domain([0, d3.max(data, d => d.value)])
          .range([height, 0]);

      const color = d3.scaleSequential()
          .domain([0, d3.max(data, d => d.value)])
          .interpolator(d3.interpolateBlues);

      // axis generators

      const xAxis = d3.axisBottom(x);
      const yAxis = d3.axisLeft(y);

      // draw bars

      g.append('g')
        .selectAll('rect')
        .data(data)
        .join('rect')
          .attr('x', d => x(d.name))
          .attr('width', x.bandwidth())
          .attr('y', d => y(d.value))
          .attr('height', d => height - y(d.value))
          .attr('fill', d => color(d.value));

      // draw axes

      g.append('g')
          .attr('transform', `translate(0,${height})`)
          .call(xAxis);

      g.append('g')
          .call(yAxis);
    </script>
</body>
</html>

  • Related