Skip to content

Instantly share code, notes, and snippets.

@bhison
Last active April 15, 2019 16:48
Show Gist options
  • Save bhison/017d2ba5b183b9ad30cc6a0742e67f2c to your computer and use it in GitHub Desktop.
Save bhison/017d2ba5b183b9ad30cc6a0742e67f2c to your computer and use it in GitHub Desktop.
d3 canvas tutorial from scratch
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
var data = [];
d3.range(5000).forEach(function(el) {
data.push({ value:el });
});
var width = 750, height = 400;
var canvas = d3.select('#container')
.append('canvas')
.attr('width', width)
.attr('height', height);
var context = canvas.node().getContext('2d');
var customBase = document.createElement('custom');
var custom = d3.select(customBase); //parent to all elements (instead of SVG)
var groupSpacing = 4,
cellSpacing = 2,
offset = height / 2,
cellSize = Math.floor((width - 11 * groupSpacing) / 100) - cellSpacing;
function databind(data){
colourScale = d3.scaleSequential(d3.interpolateSpectral)
.domain(d3.extent(data, function(d) { return d; }));
var join = custom.selectAll('custom.rect')
.data(data);
var enterSel = join.enter()
.append('custom')
.attr('class', 'rect')
.attr('x', function(d, i) {
var x0 = Math.floor(i / 100) % 10, x1 = Math.floor(i % 10);
return groupSpacing * x0 + (cellSpacing + cellSize) * (x1 + x0 * 10);
})
.attr('y', function(d, i) {
var y0 = Math.floor(i / 1000), y1 = Math.floor(i % 100 / 10);
return groupSpacing * y0 + (cellSpacing + cellSize) * (y1 + y0 * 10);
})
.attr('width', 0)
.attr('height', 0);
join
.merge(enterSel)
.transition()
.attr('width', cellSize)
.attr('height', cellSize)
//[TS] .attr not .style - we just want data attached to element
.attr('fillStyle', function(d) { return colourScale(d); });
var exitSel = join.exit()
.transition()
.attr('width', 0)
.attr('height', 0)
.remove();
} // databind()
function draw() {
context.clearRect(0, 0, width, height); // Clear the canvas.
//selects children of custom with class of rect to use for databind()
var elements = custom.selectAll('custom.rect');
elements.each(function(d,i) { // For each virtual/custom element...
var node = d3.select(this);
//Get the fillStyle from the node and apply it to the context
context.fillStyle = node.attr('fillStyle');
//Sets the position using fillRect with values from attributes
context.fillRect(
node.attr('x'), node.attr('y'), node.attr('width'), node.attr('height')
);
})
} // draw()
// === First call === //
databind(d3.range(value)); // Build the custom elements in memory.
var t = d3.timer(function(elapsed) {
draw();
if (elapsed > 300) t.stop();
}); // Timer running the draw function repeatedly for 300 ms.
//=From: https://medium.freecodecamp.org/d3-and-canvas-in-3-steps-8505c8b27444
////////GOT TO "Let the user update the number of squares"
</script>
<h3>Coloured Grid</h3>
<input type='text' id='text-input' value='5000'>
<div id='text-explain'>...takes numbers between 1 and 10k</div>
<div id='container'></div>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment