D3 Canvas Scatter
Creating a scatter chart using canvas and D3
by IPWright83
HTML
<div id="vis">
</div>
<ul>TODO
<li>Use Shadow DOM for events <a href="https://engineering.mongodb.com/post/d3-round-two-how-to-blend-html5-canvas-with-svg-to-speed-up-rendering">See here</a></li>
<li>d3.drag</li>
<li>Other styles that can be applied (stroke dasharray etc)</li>
<li>Transitions <a href="https://bocoup.com/blog/d3js-and-canvas">Maybe Useful Link</a></li>
<li>Render a Rectangle</li>
<li>Render a Path</li>
<li>Render an Area</li>
<li>Render a Line</li>
<li>Mix with SVG Axis <a href="http://bl.ocks.org/syntagmatic/2409451">Example</a></li>
</ul>
CSS
canvas {
border: thin solid red;
}
JavaScript
const DURATION = 1000;
const renderCanvas = function(context, join) {
const renderCircle = (node) => {
const selection = d3.select(node);
const cx = selection.attr("cx");
const cy = selection.attr("cy");
const r = selection.attr("r");
const fill = selection.style("fill");
const stroke = selection.style("stroke");
const strokeWidth = selection.style("stroke-width") || 1;
context.beginPath();
context.arc(cx, cy, r, 0, 2 * Math.PI);
if (fill) {
context.fillStyle = fill;
context.fill();
}
if (stroke) {
context.strokeStyle = stroke;
context.lineWidth = strokeWidth;
context.stroke();
}
};
join.each((d, i, elements) => {
const node = elements[i];
switch (node.nodeName) {
case "CIRCLE":
renderCircle(node);
}
});
}
class CanvasLayer {
test() { console.log("CANVAS"); }
}
class SVGLayer {
test() { console.log("SVG"); }
}
class Layer {
constructor(canvas) {
if(canvas) this.prototype = CanvasLayer;
else this.prototype = SVGLayer;
}
}
class Scatter extends Layer {
constructor() {
super(true);
//this.test();
this.custom = document.createElement("custom");
this.bind = d3.select(this.custom);
return this;
}
append(target) {
this.target = d3.select(target);
this.container = this.target
.append("canvas")
.attr("width", this.width)
.attr("height", this.height);
this.context = this.container.node().getContext("2d");
return this;
}
render() {
let timer = null;
const start = () => {
timer = d3.timer(() => {
this.context.clearRect(0, 0, this.width, this.height);
renderCanvas(this.context, update);
renderCanvas(this.context,...