Published
Edited
Feb 5, 2020
37 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function* rgbColorGenerator() {
let nextColor = 1;
const nextColorStep = 50;

while (nextColor < 16777216) {
const rgb = [];

rgb.push(nextColor & 0xff); // R.
rgb.push((nextColor & 0xff00) >> 8); // G.
rgb.push((nextColor & 0xff0000) >> 16); // B.

nextColor += nextColorStep;
yield `rgb(${rgb.join(',')})`;
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function draw(mouseEvent = {}) {
const hiddenCanvasColor = rgbColorGenerator();
const colorToPoint = {};
const { offsetX = null, offsetY = null } = mouseEvent;
context.clearRect(0, 0, width, height);
hiddenContext.clearRect(0, 0, width, height);
hiddenContextSelection.clearRect(0, 0, width, height);
points.forEach(point => {
// Define point geometry we will render to both the canvas and hidden canvas.
const circle = new Path2D();
circle.arc(point.x, point.y, 10, 0, 2 * Math.PI);
// Render to the hidden canvas and map a hidden canvas color to a point.
// This is where the magic happens.
const color = hiddenCanvasColor.next().value;
colorToPoint[color] = point;
hiddenContext.fillStyle = color;
hiddenContext.fill(circle);
// Render to the hidden selection canvas so we can display how the hidden canvas picking happens.
// This is just for demonstration purposes.
hiddenContextSelection.fillStyle = color;
hiddenContextSelection.fill(circle);
// If a mouse event is given, draw the hidden canvas mouse selection point.
// This is just for demonstration purposes.
if (offsetX && offsetY) {
const circle = new Path2D();
circle.arc(offsetX, offsetY, 5, 0, 2 * Math.PI);
hiddenContextSelection.fillStyle = '#4bf442';
hiddenContextSelection.fill(circle);
}
// Render to the regular canvas.
context.fillStyle = point.color;
context.fill(circle);
});
return colorToPoint;
}
Insert cell
colorToPoint = {
return draw();
}
Insert cell
Insert cell
mousemove = {
return d3.select(context.canvas).on('mousemove', () => {
const mouseEvent = d3.event;
const { offsetX, offsetY } = mouseEvent;
const { data } = hiddenContext.getImageData(offsetX, offsetY, 1, 1);
const colorKey = `rgb(${data[0]},${data[1]},${data[2]})`;
const point = colorToPoint[colorKey];

draw(mouseEvent);

if (point) {
showTooltip(point);
} else {
hideTooltip();
}
});
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more