Reputation: 1134
I'd like to implement something like the powerpoint image below. A gradient that goes between three values.
It starts at A (-1)
, the mid point is B (0)
, and the end is C (1)
.
I have realised that I can save some effort by calculating the 'start' as a-to-b, and the 'end' as b-to-c. I can do as 2 sets of 2 gradients, instead of 1 gradient with three values.
But I'm stumped (despite googling) on how to get from one colour to another - ideally in the RGB colour space.
I'd like to be able to have something like this -
const colourSpace = (value, startColor, endColor) => {...}
colorSpace(-0.25, red, yellow) // some sort of orangey color
colorSpace(1, yellow, green) // fully green
colorSpace(0.8, yellow, green) // mostly green
This isn't a front-end application, so no CSS gradients - which is what google was mostly referencing.
Thanks all, Ollie
Upvotes: 1
Views: 4605
Reputation: 92440
If you aren't too worried about being perceptually consistent across the color space (you would need to work in something like LAB mode to do that), you can just take the linear interpolation in RGB space. Basically you take a distance (between 0 and 1), multiply it by the different in the coordinates, and add it to the first one. This will allow you to find arbitrary points (i.e colors) along the line between any two colors.
For example between red and yellow:
let canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');
let rgb1 = [255, 0, 0] // red
let rgb2 = [255, 255, 0] // yellow
function getPoint(d, a1, a2) {
// find a color d% between a1 and a2
return a1.map((p, i) => Math.floor(a1[i] + d * (a2[i] - a1[i])))
}
// for demo purposes fill a canvas
for (let i = 0, j = 0; i < 1; i += .002, j++) {
let rgb = getPoint(i, rgb1, rgb2)
ctx.fillStyle = `rgba(${rgb.join(",")}, 1)`
ctx.fillRect(j, 0, 1, 200);
}
<canvas id="canvas" width="500"></canvas>
You can repeat this to get multiple 'stops' in the gradient.
Upvotes: 1