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
];
...