EN
JavaScript - color points based distribution model (heatmap color model)
6
points
In this short article, we would like to show how in JavaScript, we create color points distribution model.
That model is built using middle color points that are used to compute middle points when needed.
e.g. it can be used to color 3D chart values.

Practical example:
// ONLINE-RUNNER:browser;
const findMultiple = (base, value) => {
return base * Math.ceil(value / base);
};
const findStep = (space, count) => {
return space / count;
};
const keepRange = (min, max, value) => {
if (value < min) {
return min;
}
if (value > max) {
return max;
}
return value;
};
const createDenormalizer = (min, max, size) => {
const range = max - min;
return (versor) => {
return min + versor * range;
};
};
// Creates color points based distribution model that provides smooth color transition.
// Arguments:
// points indicates middle color points
// resolution indicates smooth transition quantization
// Result: retuns function that returns calculated RGB color for indicated versor (from 0 to 1)
//
const createPointsDistribution = (points, resolution) => {
if (resolution < 1) {
throw new Error('It is required to use positive resolution.');
}
const space = points.length - 1;
if (space < 1) {
throw new Error('It is required to provide at least 2 points.');
}
const count = findMultiple(space, resolution);
const step = findStep(space, count);
let p1 = points[0];
let p2;
const colors = new Array(count);
for (let i = 1, k = 0; i < points.length; ++i) {
p2 = points[i];
const calculateRed = createDenormalizer(p1.red, p2.red);
const calculateGreen = createDenormalizer(p1.green, p2.green);
const calculateBlue = createDenormalizer(p1.blue, p2.blue);
for (let t = 0; t < 1.0; t += step, k += 1) {
colors[k] = {
red: Math.round(calculateRed(t)),
green: Math.round(calculateGreen(t)),
blue: Math.round(calculateBlue(t))
};
}
p1 = p2;
}
const limit = count - 1;
return (versor) => {
const value = Math.floor(versor * count);
const index = keepRange(0, limit, value);
return colors[index];
};
};
// Helpers:
const drawPixel = (data, width, x, y, rgb) => {
const roundedX = Math.round(x);
const roundedY = Math.round(y);
const index = 4 * (width * roundedY + roundedX);
data[index + 0] = rgb.red;
data[index + 1] = rgb.green;
data[index + 2] = rgb.blue;
data[index + 3] = 255;
};
const drawDistribution = (canvas, distribution) => {
const context = canvas.getContext('2d');
const image = context.createImageData(canvas.width, canvas.height);
for (let y = 0; y < canvas.height; ++y) {
for (let x = 0; x < canvas.width; ++x) {
const versor = 1.0 - y / canvas.height; // scales y value to versor value (from 0 to 1)
const color = distribution.call(null, versor); // returns pixel color
drawPixel(image.data, canvas.width, x, y, color);
}
}
context.putImageData(image, 0, 0);
};
// Usage example:
const points = [
{red: 23, green: 23, blue: 230},
{red: 23, green: 230, blue: 229},
{red: 23, green: 230, blue: 27},
{red: 229, green: 230, blue: 23},
{red: 230, green: 23, blue: 23}
];
const distribution = createPointsDistribution(points, 200);
// To get pixel color just use:
//
// const versor = 0.0; // versor should be from 0.0 to 1.0
// const color = distribution.call(null, versor); // color has RGB format
const canvas = document.createElement('canvas');
canvas.width = 50;
canvas.height = 400;
drawDistribution(canvas, distribution);
document.body.appendChild(canvas);
Example colors:
Example: Surface Wave - Apache ECharts | ![]() |
| ![]() |
| ![]() |