iTake
iTake

Reputation: 315

Scaling in d3js

If I have a set of data numbers that are percentages ranging from -0.75 to 0.3, and I want to create a heat map where -0.75 are "bright red" tiles and .3 values are "bright green values" and everything in between is scaled between that.

I currently have this:

js

var color = d3.scale.quantize()
.domain([-.7, .3])
.range(d3.range(11).map(function(d) { return "q" + d + "-11"; }));

css

.RdYlGn .q0-11{fill:rgb(255,0,0)}
.RdYlGn .q1-11{fill:rgb(255,50,50)}
.RdYlGn .q2-11{fill:rgb(255,100,100)}
.RdYlGn .q3-11{fill:rgb(255,150,150)}
.RdYlGn .q4-11{fill:rgb(255,200,200)}
.RdYlGn .q5-11{fill:rgb(255,255,255)}
.RdYlGn .q6-11{fill:rgb(200,255,200)}
.RdYlGn .q7-11{fill:rgb(150,255,150)}
.RdYlGn .q8-11{fill:rgb(100,255,100)}
.RdYlGn .q9-11{fill:rgb(50,255,50)}
.RdYlGn .q10-11{fill:rgb(0,255,0)}

But the numbers don't seem to scale right. The percentages seem to be scaled like so:

.3 = q0  Green
.0 = q2
-.1 = q4
-.5 = q5  White
-.7 = q11 Red

It makes sense that -.5 is my middle value of white, because that is the median of .3 and -.7, but I don't want it to be that. Any help?

Upvotes: 0

Views: 1052

Answers (2)

Ben Rudolph
Ben Rudolph

Reputation: 2517

Take a look at d3's built in color interpolators here

In your case it would look something like this:

var interpolator = d3.interpolateHsl('rgb(255,0,0)', 'rgb(0,255,0)');
var scale = d3.scale.linear()
  .domain([-.7, .3])
  .range([0, 1])
// interpolator(scale(0)) will return a color in between red and green 

Upvotes: 2

Dick Fox
Dick Fox

Reputation: 2994

Fortunately there is a very simple way to accomplish what you want. Just use a polylinear scale, which is just a regular d3.scale.linear() with anchor points at each value where a new color should start.

To have red for negative values, white at zero, and green for positive, use:

polylinear_color = d3.scale.linear()
    .domain([-0.3, 0, 0.7])
    .range(['rgb(255,0,0)','rgb(255,255,255)','rgb(0,255,0)'])

The scale does all the interpolation and instead of using classes you just set .attr('fill',function(d){return polylinear_color(d);}); on the things being colored.

I made a jsfiddle to illustrate, here.

Upvotes: 5

Related Questions