Reputation: 39078
I've created a set of bars that get recolored upon new data entry. The idea's to indicate the value not only by their width but also their color. To make it easy, as a first step, I picked blue and red (the thresholds of 40 and 160 are irrelevant), which resulted in the following.
.style("background-color", function (d) {
var low = 40;
var high = 160;
if (d < low) return "#0000ff";
if (d > high) return "#ff0000";
var ratio = (d - low) / (high - low);
return "#" + Math.round(255 * ratio).toString(16)
+ "00" + Math.round(255 * (1 - ratio)).toString(16);
})
While it works, I realize that it poses a maintnance issue. If I suddenly wish to go from green to yellow, I'll need to change quite a bit of the calculations. And trying out different color sets will turn out to a tedious and time consuming anti-fun.
There's got to be a more like-a-boss-ish way?
I can think of something like declaring the extreme colors, parsing them into separate RGB channels, multiplying the ratio and reconstructing the string again like below. However, I have a feeling that D3 offers something much, much smoother than that. Also, as an extra bonus, I'd like to use the color names, not the hexa codes.
var color = "#abcdef";
var ratio = 0.7;
var oldRed = color.substring(1,3);
var tmpRed = Math.round(parseInt(oldRed,16) * ratio);
var newRed = newRed.toString(16);
Upvotes: 2
Views: 133
Reputation: 8376
You can solve 1) and 2) using interpolators:
var red = d3.rgb("red")
var blue = d3.rgb("blue")
return d3.interpolate(red, blue)(my_factor)
The wiki also lists various possibilities for creating the rgb objects:
For 3), you can use transitions, for example:
my_obj
.style("fill", start_color)
.transition()
.attr("fill", end_color)
.duration(1000)
See: D3 Wiki - interpolators, D3 Wiki - colors and Creating transitions with d3
Upvotes: 5