Chartjs-Histogram like chart with intensity colored columns and per bin opacity to show intensity

1👍

First at all, I’m really impressed of what you already achieved, your chart looks just great!

Presuming your data is present in an array named ‘input’, I first count the occurrences of identical objects using Array.reduce().

const countedData = input.reduce((acc, v) => {
  const existing = acc.find(o => o.x == v.x && o.y == v.y);
  if (existing) {
    existing.count += 1;
  } else {
    acc.push({ x: v.x, y: v.y, count: 1 });
  }
  return acc;
}, []);

With the data you provided, countedData will then contain the following objects.

[
  { "x": 2, "y": 10, "count": 3 },
  { "x": 8, "y": 50, "count": 4 }
]

Then I’ll need a function that provides the opacity for every combination of x and y:

function getOpacity(x, y) {
  const obj = countedData.find(o => o.x == x && o.y == y);
  if (obj) {
    return obj.count < 4 ? 0.7 : 1;
  }
  return 0.2;
}

The only part left is to create an array of backgroundColor that uses above mentioned getOpacity function.

backgroundColor: data.map((v, index) => "rgba("+R+", "+G+", "+B+", " + getOpacity(index + 1, i + 25) + ")"),

Please have a look at your amended runnable code below:

const input = [ {x:2, y:10},{x:2, y:10},{x:2, y:10},{x:8, y:50},{x:8, y:50},{x:8, y:50} ,{x:8, y:50} ];
var labels = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24"];
var data = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];

const countedData = input.reduce((acc, v) => {
  const existing = acc.find(o => o.x == v.x && o.y == v.y);
  if (existing) {
    existing.count += 1;
  } else {
    acc.push({ x: v.x, y: v.y, count: 1 });
  }
  return acc;
}, []);

function getOpacity(x, y) {
  const obj = countedData.find(o => o.x == x && o.y == y);
  if (obj) {
    return obj.count < 4 ? 0.7 : 1;
  }
  return 0.2;
}

var datasets = [];
var R = 0;
var G = 255;
var B = 2;

for ( var i = 1; i < 26; i ++){
  R += 8;
  G -= 4;
  B += 1;
  datasets.push ({ 
    data: data,
    backgroundColor: data.map((v, index) => "rgba("+R+", "+G+", "+B+", " + getOpacity(index + 1, i) + ")"),
    label: 'Bad Style',
    hoverBackgroundColor: "#7E57C2",
    hoverBorderWidth: 0,
    borderWidth: 1.5,
   });
}

R = 153;
G = 153;
B = 0;
for ( var i = 1; i < 30; i ++) {
  R += 8;
  G -= 5;
  B += 0;
  datasets.push ({ 
    data: data,
    backgroundColor: data.map((v, index) => "rgba("+R+", "+G+", "+B+", " + getOpacity(index + 1, i + 25) + ")"),
    label: 'Bad Style',
    hoverBackgroundColor: "#7E57C2",
    hoverBorderWidth: 0,
    borderWidth: 1.5,
   });
}

var bar_ctx = document.getElementById('bar-chart');
bar_ctx.style.backgroundColor = 'rgba(0,0,0,255)';
var bar_chart = new Chart(bar_ctx, {
    type: 'bar',
    data: {
        labels: labels,
        datasets: datasets
    },
    options: {
     		animation: {
        	duration: 10,
        },
        scales: {
          xAxes: [{ 
          	stacked: true, 
            gridLines: { display: false },
            }],
          yAxes: [{ 
          	stacked: true, 
            gridLines: { display: false },
            }],
        },
        legend: {display: false}
    },
   }
);
<script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js'></script>
<canvas id="bar-chart" width="600" height="350"></canvas>

Leave a comment