Heatmap X-Zoomable

Using CandyGraph

by flek

HTML

<script src="https://unpkg.com/[email protected]/gl-matrix-min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/index.js"></script>
<script src="https://unpkg.com/[email protected]/dist/dom-2d-camera.min.js"></script>
<canvas id="canvas" />

CSS

#canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 0, 0, 0.1);
}

JavaScript

const t00 = performance.now();

// Data
const nCols = 2000;
const nRows = 250;

const cellSize = 6;
const cellSpacing = 0;

const width = nCols * cellSize + (nCols - 1) * cellSpacing;
const height = nRows * cellSize + (nRows - 1) * cellSpacing;

const data = { rects: [], colors: [] }

for (let i = 0; i < nRows; i++) {
  for (let j = 0; j < nCols; j++) {
    const c = Math.random();
    const x = j * (cellSize + cellSpacing);
    const y = i * (cellSize + cellSpacing);
    
    data.rects.push(x, y, cellSize, cellSize);
    data.colors.push(c, c, c, 1.0);
  }
}

// DOM
const canvas = document.getElementById('canvas');
const stageBBox = canvas.getBoundingClientRect();
const scale = window.devicePixelRatio;
const viewport = {
	x: 0,
  y: 0,
  width: stageBBox.width * scale,
  height: stageBBox.height * scale
};

canvas.style.width = `${stageBBox.width}px`;
canvas.style.height = `${stageBBox.height}px`;
canvas.width = viewport.width;
canvas.height = viewport.height;

// Camera
const maxXScale = cellSize / (stageBBox.width / nCols);
const camera = window.createDom2dCamera(
	canvas,
  {
  	isPan: [true, false],
    isZoom: [true, false],
    scaleBounds: [1, maxXScale]
  }
);

// CandyGraph
const cg = new window.candygraph.CandyGraph();
cg.canvas.width = Math.max(viewport.width, 1024 * scale);
cg.canvas.height = Math.max(viewport.height, 1024 * scale);

// Make data reusable for better performance
data.rects = window.candygraph.createDataset(cg, data.rects);
data.colors = window.candygraph.createDataset(cg, data.colors);

const xScale = window.candygraph.createLinearScale([0, width], [0, stageBBox.width * scale]);
const yScale = window.candygraph.createLinearScale([0, height], [stageBBox.height * scale, 0]);

const coords = window.candygraph.createCartesianCoordinateSystem(xScale, yScale);

const scratch1 = new Float32Array(4);
const scratch2 = new Float32Array(4);

function getViewInPx(view) {
  scratch2[0] = -1;
  scratch2[1] = 0;
  scratch2[2] = 0;
  scratch2[3] =...