Heatmaps in JavaScript

How to make a D3.js-based heatmap in javascript with a matrix. Seven examples of colored and labeled heatmaps with custom colorscales.


Plotly Studio: Transform any dataset into an interactive data application in minutes with AI. Try Plotly Studio now.

var data = [
  {
    z: [[1, 20, 30], [20, 1, 60], [30, 60, 1]],
    type: 'heatmap'
  }
];

Plotly.newPlot('myDiv', data);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var data = [\n {\n z: [[1, 20, 30], [20, 1, 60], [30, 60, 1]],\n type: 'heatmap'\n }\n];\n\nPlotly.newPlot('myDiv', data);\n"}">

In this example we also show how to ignore hovertext when we have missing values in the data by setting the hoverongaps to False.

var data = [
  {
    z: [[1, null, 30, 50, 1], [20, 1, 60, 80, 30], [30, 60, 1, -10, 20]],
    x: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
    y: ['Morning', 'Afternoon', 'Evening'],
    type: 'heatmap',
    hoverongaps: false
  }
];

Plotly.newPlot('myDiv', data);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var data = [\n {\n z: [[1, null, 30, 50, 1], [20, 1, 60, 80, 30], [30, 60, 1, -10, 20]],\n x: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],\n y: ['Morning', 'Afternoon', 'Evening'],\n type: 'heatmap',\n hoverongaps: false\n }\n];\n\nPlotly.newPlot('myDiv', data);\n"}">
var xValues = ['A', 'B', 'C', 'D', 'E'];

var yValues = ['W', 'X', 'Y', 'Z'];

var zValues = [
  [0.00, 0.00, 0.75, 0.75, 0.00],
  [0.00, 0.00, 0.75, 0.75, 0.00],
  [0.75, 0.75, 0.75, 0.75, 0.75],
  [0.00, 0.00, 0.00, 0.75, 0.00]
];

var colorscaleValue = [
  [0, '#3D9970'],
  [1, '#001f3f']
];

var data = [{
  x: xValues,
  y: yValues,
  z: zValues,
  type: 'heatmap',
  colorscale: colorscaleValue,
  showscale: false
}];

var layout = {
  title: {
    text: 'Annotated Heatmap'
  },
  annotations: [],
  xaxis: {
    ticks: '',
    side: 'top'
  },
  yaxis: {
    ticks: '',
    ticksuffix: ' ',
    width: 700,
    height: 700,
    autosize: false
  }
};

for ( var i = 0; i < yValues.length; i++ ) {
  for ( var j = 0; j < xValues.length; j++ ) {
    var currentValue = zValues[i][j];
    if (currentValue != 0.0) {
      var textColor = 'white';
    }else{
      var textColor = 'black';
    }
    var result = {
      xref: 'x1',
      yref: 'y1',
      x: xValues[j],
      y: yValues[i],
      text: zValues[i][j],
      font: {
        family: 'Arial',
        size: 12,
        color: 'rgb(50, 171, 96)'
      },
      showarrow: false,
      font: {
        color: textColor
      }
    };
    layout.annotations.push(result);
  }
}

Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var xValues = ['A', 'B', 'C', 'D', 'E'];\n\nvar yValues = ['W', 'X', 'Y', 'Z'];\n\nvar zValues = [\n [0.00, 0.00, 0.75, 0.75, 0.00],\n [0.00, 0.00, 0.75, 0.75, 0.00],\n [0.75, 0.75, 0.75, 0.75, 0.75],\n [0.00, 0.00, 0.00, 0.75, 0.00]\n];\n\nvar colorscaleValue = [\n [0, '#3D9970'],\n [1, '#001f3f']\n];\n\nvar data = [{\n x: xValues,\n y: yValues,\n z: zValues,\n type: 'heatmap',\n colorscale: colorscaleValue,\n showscale: false\n}];\n\nvar layout = {\n title: {\n text: 'Annotated Heatmap'\n },\n annotations: [],\n xaxis: {\n ticks: '',\n side: 'top'\n },\n yaxis: {\n ticks: '',\n ticksuffix: ' ',\n width: 700,\n height: 700,\n autosize: false\n }\n};\n\nfor ( var i = 0; i < yValues.length; i++ ) {\n for ( var j = 0; j < xValues.length; j++ ) {\n var currentValue = zValues[i][j];\n if (currentValue != 0.0) {\n var textColor = 'white';\n }else{\n var textColor = 'black';\n }\n var result = {\n xref: 'x1',\n yref: 'y1',\n x: xValues[j],\n y: yValues[i],\n text: zValues[i][j],\n font: {\n family: 'Arial',\n size: 12,\n color: 'rgb(50, 171, 96)'\n },\n showarrow: false,\n font: {\n color: textColor\n }\n };\n layout.annotations.push(result);\n }\n}\n\nPlotly.newPlot('myDiv', data, layout);\n"}">
function linspace(a,b,n) {
  return d3.range(n).map(function(i){return a+i*(b-a)/(n-1);});
}
//number of spiral loops

var nspiral = 2;

// angle

var th = linspace(((-Math.PI) / 13), (2 * Math.PI * nspiral), 1000);

//Empty Value Containers

var xValues = [];
var yValues = [];
var yShift = [];
var finalX = [];
var finalY = [];

//spiral

for(var i = 0; i < th.length; i++){
  var a = 1.120529;
  var b = 0.306349;
  var r = a * Math.exp((-b) * th[i]);
  var xResult = (r * Math.cos(th[i]));
  var yResult = (r * Math.sin(th[i]));
  xValues.push(xResult);
  yValues.push(yResult);
}

function getMaxOfArray(numArray) {
  return Math.max.apply(null, numArray);
};

function getMinOfArray(numArray) {
  return Math.min.apply(null, numArray);
};

//Shift spiral north so that it is centered

var yShift = (1.6 - (getMaxOfArray(yValues) - getMinOfArray(yValues))) / 2;

var spiralTrace = {
  x: xValues.map(function(xi) { return -(xi) + xValues[0]; }),
  y: yValues.map(function(yi) { return yi - yValues[0] + yShift; }),
  type: 'scatter',
  line: {
    color: 'white',
    width: 3
  }
};

//Build the rectangles as a heatmap and specify the edges of the heatmap squares

var phi = (1 + Math.sqrt(5)) / 2;
var xe = [0, 1, (1 + (1 / Math.pow(phi,4))), 1 + (1 / Math.pow(phi,3)), phi];
var ye = [0, (1 / Math.pow(phi,3)), (1 / Math.pow(phi,3)) + (1 / Math.pow(phi,4)), (1 / Math.pow(phi,2)), 1];

var zValues = [
  [13, 3, 3, 5],
  [13, 2, 1, 5],
  [13, 10, 11, 12],
  [13, 8, 8, 8]
];

var hm = {
  x: xe,
  y: ye.map(function(yi) { return yi + yShift; }),
  z: zValues,
  type: 'heatmap',
  colorscale: 'Viridis'
};

var axisTemplate = {
  range: [0, 1.6],
  autorange: false,
  showgrid: false,
  zeroline: false,
  linecolor: 'black',
  showticklabels: false,
  ticks: ''
};

var data = [spiralTrace, hm];

var layout = {
  title: {
    text: 'Heatmap with Unequal Block Sizes'
  },
  margin: {
    t: 200,
    r: 200,
    b: 200,
    l: 200
  },
  xaxis: axisTemplate,
  yaxis: axisTemplate,
  showlegend: false,
  width: 700,
  height: 700,
  autosize: false
};

Plotly.newPlot('myDiv', data, layout);
</script>\n\t<script src="/?originalUrl=https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fd3%2F3.5.17%2Fd3.min.js"></script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"function linspace(a,b,n) {\n return d3.range(n).map(function(i){return a+i*(b-a)/(n-1);});\n}\n//number of spiral loops\n\nvar nspiral = 2;\n\n// angle\n\nvar th = linspace(((-Math.PI) / 13), (2 * Math.PI * nspiral), 1000);\n\n//Empty Value Containers\n\nvar xValues = [];\nvar yValues = [];\nvar yShift = [];\nvar finalX = [];\nvar finalY = [];\n\n//spiral\n\nfor(var i = 0; i < th.length; i++){\n var a = 1.120529;\n var b = 0.306349;\n var r = a * Math.exp((-b) * th[i]);\n var xResult = (r * Math.cos(th[i]));\n var yResult = (r * Math.sin(th[i]));\n xValues.push(xResult);\n yValues.push(yResult);\n}\n\nfunction getMaxOfArray(numArray) {\n return Math.max.apply(null, numArray);\n};\n\nfunction getMinOfArray(numArray) {\n return Math.min.apply(null, numArray);\n};\n\n//Shift spiral north so that it is centered\n\nvar yShift = (1.6 - (getMaxOfArray(yValues) - getMinOfArray(yValues))) / 2;\n\nvar spiralTrace = {\n x: xValues.map(function(xi) { return -(xi) + xValues[0]; }),\n y: yValues.map(function(yi) { return yi - yValues[0] + yShift; }),\n type: 'scatter',\n line: {\n color: 'white',\n width: 3\n }\n};\n\n//Build the rectangles as a heatmap and specify the edges of the heatmap squares\n\nvar phi = (1 + Math.sqrt(5)) / 2;\nvar xe = [0, 1, (1 + (1 / Math.pow(phi,4))), 1 + (1 / Math.pow(phi,3)), phi];\nvar ye = [0, (1 / Math.pow(phi,3)), (1 / Math.pow(phi,3)) + (1 / Math.pow(phi,4)), (1 / Math.pow(phi,2)), 1];\n\nvar zValues = [\n [13, 3, 3, 5],\n [13, 2, 1, 5],\n [13, 10, 11, 12],\n [13, 8, 8, 8]\n];\n\nvar hm = {\n x: xe,\n y: ye.map(function(yi) { return yi + yShift; }),\n z: zValues,\n type: 'heatmap',\n colorscale: 'Viridis'\n};\n\nvar axisTemplate = {\n range: [0, 1.6],\n autorange: false,\n showgrid: false,\n zeroline: false,\n linecolor: 'black',\n showticklabels: false,\n ticks: ''\n};\n\nvar data = [spiralTrace, hm];\n\nvar layout = {\n title: {\n text: 'Heatmap with Unequal Block Sizes'\n },\n margin: {\n t: 200,\n r: 200,\n b: 200,\n l: 200\n },\n xaxis: axisTemplate,\n yaxis: axisTemplate,\n showlegend: false,\n width: 700,\n height: 700,\n autosize: false\n};\n\nPlotly.newPlot('myDiv', data, layout);\n"}">