Reputation: 17091
I'm trying to create something a little like a quantize scale, but act like a linear color scale?
When I try to put multiple colors into a linear scale, it seems to only scale between the first two colors.
I'd like multiple colors like a quantize scale, but fade between those colors. I'm unsure if this is possible.
//red and green works ok
var color = d3.scale.linear()
.range(['red','green']);
//doesn't work - only red and green show
var color = d3.scale.linear()
.range(['red','green', 'blue']);
//red green and blue show, however it doesn't fade between the colors
var color = d3.scale.quantize()
.range(['red','green', 'blue']);
Upvotes: 24
Views: 34609
Reputation: 1260
Anto's solution works great if you want to blend 3 colors. In my case, I needed a way to blend an arbitrary number of colors. For me, the trick was to set up the domain correctly. Take for example, the following array of colors:
var colors = ['#084594', '#2171b5', '#4292c6', '#6baed6', '#9ecae1', '#c6dbef', '#eff3ff'];
You can create a domain array with values from -1 to +1 like this:
var domain = [-1];
var increment = 2/(colors.length-1);
for (var i=0; i<colors.length-2; i++){
var previous = domain[domain.length-1];
domain.push(previous+increment);
}
domain.push(1);
Once the domain array is created, you can create a color function like this:
var getColor = d3.scaleLinear()
.domain(domain)
.range(colors);
If you want to get color values at specific percentages (like chroma does), you can do something like this:
var p = 0.25; //Valid range for p is 0.0-1.0
var x = (p*2)-1;
var color = d3.color(getColor(x));
console.log(color.formatHex());
Upvotes: 0
Reputation: 11258
You have to use domain 'pivot' value like:
d3.scale.linear()
.domain([0, pivot, max])
.range(['red', 'green', 'blue']);
From the documentation for continuous scale domains:
Although continuous scales typically have two values each in their domain and range, specifying more than two values produces a piecewise scale. For example, to create a diverging color scale that interpolates between white and red for negative values, and white and green for positive values, say:
var color = d3.scaleLinear()
.domain([-1, 0, 1])
.range(["red", "white", "green"]);
color(-0.5); // "rgb(255, 128, 128)"
color(+0.5); // "rgb(128, 192, 128)"
Upvotes: 37