'Is there a way to perfectly align rows in a heatmap where the yAxis is the month?

The Problem

I am trying to generate a heatmap with highcharts. The chart will show the average PM2.5 value over x years for a day in a month. The issue is that the rows are not aligned because of the different lengths of the months.

I expect the cells in the grid to not be overflowing to the cell above it like in the large heatmap demo. In my example the overflow is visible when hovering a cell.

What I Have Tried

I have tried reducing the rowsize a little bit (e.g. 24 * 25 * 36e5) but it results in uneven white space between the rows.

In theory I could use categories but I also need to have the possibility to illustrate the daily variation over a year using the yAxis hour and xAxis for julian day. The xAxis in this case would need to be formatted as month (%B).

The proper solution would be to make the grid symmetrical but since I use datetime on both axes, I can't manually make all days of the months 31 days long.

Current Code

let data = [];
// random data generation
const daysPerMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let month;
// yAxis: month
for (let i = 0; i < 12; i++) {
  month = new Date(2022, i, 2).getTime(); // use second hour to align the cell to the correct month
  // xAxis: days
  for (let j = 0; j < daysPerMonth[i]; j++) {
    const randomAdden = Math.random() * (5 - 1) + 1;
    const plusOrMinus = Math.random() < 0.5 ? -1 : 1;
    let previousValue = 50; // starting value
    if (data[data.length - 1] != null) {
      previousValue = data[data.length - 1][2];
    }
    const day = j * 24 * 36e5;
    data.push([day, month, Math.max(previousValue + randomAdden * plusOrMinus, 0)]);
  }
}

Highcharts.chart('container', {
  accessibility: {
      enabled: false, // disabled to remove console warning on stack overflow
  },
  title: {
    text: 'PM2.5 random heat map',
    align: 'left',
    x: 40
  },

  subtitle: {
    text: 'PM2.5 average per day and month over a year',
    align: 'left',
    x: 40
  },

  xAxis: {
    type: 'datetime',
    min: 0,
    max: 36e5 * 24 * 31,
    labels: {
      align: 'left',
      x: 5,
      y: 14,
      format: '{value:%e}'
    },
  },

  yAxis: {
    type: 'datetime',
    min: Date.UTC(2022, 0, 1),
    max: Date.UTC(2022, 11, 31),
    title: {
      text: null
    },
    gridLineWidth: 0,
    labels: {
      format: '{value:%B}' // long month
    },
    startOnTick: false,
    endOnTick: false,
    tickmarkPlacement: 'on',
    tickInterval: 24 * 31 * 36e5,
    showLastLabel: false,
  },

  colorAxis: {
    stops: [
      [0.048, '#00e400'],
      [0.14, '#ffff00'],
      [0.22, '#ff7e00'],
      [0.6, '#ff0000'],
      [0.9999, '#8f3f97'], // if equal to max (250)
      [1, '#7e0023'] // more than max (250)
    ],
    min: 0,
    max: 251,
    startOnTick: false,
    endOnTick: false,
    labels: {
      format: '{value} µg/m³'
    }
  },

  series: [{
    type: 'heatmap',
    data: data,
    borderWidth: 0,
    nullColor: '#EFEFEF',
    colsize: 24 * 36e5,
    rowsize: 24 * 31 * 36e5,
    tooltip: {
      headerFormat: 'PM2.5<br/>',
      pointFormat: '{point.x:%e} {point.y:%b}: <b>{point.value} µg/m³</b>'
    }
  }]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/heatmap.js"></script>
<div id="container" />


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source