Search code examples
javascripthtmlcolorsheatmap

Javascript color stop heatmap line canvas


I have a single number data in array (array can be any number length):

I want to create something like this on canvas, present colored data in one line (there are 2 lines on the picture for example): enter image description here

White represents zeros, and the higher the number, color would be darker.

I cant find anything similar, the only thing I found is: What is the algorithm to create colors for a heatmap?

First thing I think I would need to normalize values from 0 - 1. And then ofcourse convert this to colors.

I dont want to use external libraries (I looked and Chartjs doesnt have such example), but simple canvas.

var values = [0, 4, 44, 11, 55, 2, 6, 0, 0, 0, 0, 0, 0, 3, 2, 4, 2, 22, 55, 6, 44, 34, 56, 26, 87, 93, 112, 115, 45, 6]

function normalize(min, max) {
  var delta = max - min;
  return function(val) {
    return (val - min) / delta;
  };
}

values = values.map(normalize(Math.min(...values), Math.max(...values)));

console.log(values)

var canvas = document.querySelector('#myCanvas'),
ctx = canvas.getContext('2d');
<canvas id="myCanvas" width="800" height="50"></canvas>


Solution

  • You can use the native fillRect method of canvas with a HSL-based fillStyle for the colors.

    Here is one possible implementation, assuming that you want to display the data points as rectangles evenly spaced throughout the canvas:

    var values = [0, 4, 44, 11, 55, 2, 6, 0, 0, 0, 0, 0, 0, 3, 2, 4, 2, 22, 55, 6, 44, 34, 56, 26, 87, 93, 112, 115, 45, 6]
    
    function normalize(min, max) {
      var delta = max - min;
      return function(val) {
        return (val - min) / delta;
      };
    }
    
    values = values.map(normalize(Math.min(...values), Math.max(...values)));
    
    console.log(values)
    
    var canvas = document.querySelector('#myCanvas'),
    ctx = canvas.getContext('2d');
    
    var width = canvas.width;
    var height = canvas.height;
    var lengthOfEachValue = width / values.length;
    
    values.forEach((value, index)=>{
        ctx.fillStyle = `hsl(235, 100%, ${(1 - value) * 100}%)`;
        ctx.fillRect(index * lengthOfEachValue, 0, lengthOfEachValue, height);
    })
    <canvas id="myCanvas" width="800" height="50"></canvas>