Honeycomb (Hexagon Cells) in React

Using ApexCharts with React

This Honeycomb (Hexagon Cells) example wires ApexCharts into React through the react-apexcharts component.

Install it with npm install react-apexcharts apexcharts, then mount the chart with <Chart type="..." options={options} series={series} />.

React charts guide
import React from 'react'
import ReactApexChart from 'react-apexcharts'
import './styles.css'

// Seeded PRNG so the honeycomb is identical on every load (stable snapshots).
var __seed = 0x51ab3c21
function rand() {
  __seed |= 0
  __seed = (__seed + 0x6d2b79f5) | 0
  var t = Math.imul(__seed ^ (__seed >>> 15), 1 | __seed)
  t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
  return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}

// Signal strength across the floor: distance falloff from two access points
// plus gentle noise, so the color bands form contiguous regions instead of
// random speckle.
var ROWS = 12
var COLS = 20
var accessPoints = [
  { col: 4, row: 3 },
  { col: 14, row: 8 },
]

function coverage(col, row) {
  var best = 0
  for (var k = 0; k < accessPoints.length; k++) {
    var dx = col - accessPoints[k].col
    var dy = (row - accessPoints[k].row) * 1.6
    var d = Math.sqrt(dx * dx + dy * dy)
    best = Math.max(best, 96 - d * 7.5)
  }
  return Math.max(8, Math.min(100, Math.round(best + (rand() - 0.5) * 10)))
}

// First series renders as the bottom row, so build L..A to read A..L top-down.
function generateFloor() {
  var series = []
  for (var r = ROWS - 1; r >= 0; r--) {
    var data = []
    for (var c = 0; c < COLS; c++) {
      data.push({ x: String(c + 1), y: coverage(c, r) })
    }
    series.push({ name: String.fromCharCode(65 + r), data: data })
  }
  return series
}

const ApexChart = () => {
  const [state, setState] = React.useState({
    series: generateFloor(),
    options: {
      chart: {
        height: 420,
        type: 'heatmap',
      },
      plotOptions: {
        heatmap: {
          shape: 'hexagon',
          enableShades: false,
          colorScale: {
            ranges: [
              {
                from: 0,
                to: 39,
                name: 'Weak',
                color: '#A7E0F4',
              },
              {
                from: 40,
                to: 59,
                name: 'Fair',
                color: '#64C6E8',
              },
              {
                from: 60,
                to: 79,
                name: 'Good',
                color: '#2296CB',
              },
              {
                from: 80,
                to: 100,
                name: 'Excellent',
                color: '#0B6E9E',
              },
            ],
          },
        },
      },
      stroke: {
        width: 2,
        colors: ['#fff'],
      },
      dataLabels: {
        enabled: false,
      },
      tooltip: {
        y: {
          title: {
            // The honeycomb offsets shift each row a quarter cell off its column
            // tick, so name both coordinates in the tooltip: "Zone 7 · Row D: 78"
            formatter: function (seriesName, opts) {
              return (
                'Zone ' +
                opts.w.globals.labels[opts.dataPointIndex] +
                ' · Row ' +
                seriesName +
                ':'
              )
            },
          },
        },
      },
      xaxis: {
        type: 'category',
      },
      title: {
        text: 'Office Wi-Fi Coverage by Floor Zone',
      },
    },
  })

  return (
    <div>
      <div id="chart">
        <ReactApexChart
          options={state.options}
          series={state.series}
          type="heatmap"
          height={420}
        />
      </div>
    </div>
  )
}

export default ApexChart