Candygraph Heatmap

by flek

HTML

<script src="https://unpkg.com/[email protected]/lib/index.js"></script>
<div id="heatmap">
  <canvas id="canvas"></canvas>
  <div id="scroll-container">
    <div id="scroll"></div>
  </div>
</div>

CSS

#heatmap {
  position: absolute;
  top: 1rem;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  background: rgba(255, 0, 0, 0.1);
}

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

#scroll-container {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: auto;
}

#scroll {
  position: absolute;
  top: 0;
  left: 0;
}

JavaScript

const t00 = performance.now();


// Data
const nCols = 1000;
const nRows = 100;

const cellSize = 6;
const cellSpacing = 1;

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 scrollContainer = document.getElementById('scroll-container');
const scroll = document.getElementById('scroll');

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;

scroll.style.width = `${width}px`;
scroll.style.height = `${height}px`;

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 = cg.reusableData(data.rects);
data.colors = cg.reusableData(data.colors);

const xScale = cg.scale.linear([0, width], [0, width * scale]);
const yScale = cg.scale.linear([0, height], [0, height * scale]);

const coords = cg.coordinate.cartesian(xScale, yScale);

console.log(
  'Scale test:\n',
  `0     => ${yScale.toRange(0)}\n`,
  `${height/2} => ${yScale.toRange(height/2)}\n`,
  `${height}   => ${yScale.toRange(height)}`
)

function draw() {
  cg.clear([1, 1, 1, 1]);
  
  xScale.range = [
  	-scrollContainer.scrollLeft * scale,
    (width - scrollContainer.scrollLeft) * scale
  ];

...