24

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']);

2 Answers 2

37

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)"
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks Anto, I'm in a different world now and haven't had a chance to give it a shot, but that sounds like a good idea +1 from me.
Your link has gone broken due to move of API docs as v.4 of D3 is up.
@KonradViltersten this is a great reason why people shouldn't post a link as an answer.
@JasTonAChair I agree with you on th eprinciple. However, some links are to be relied on (MSDN, jQuery API etc.) but only and strictly after very careful consideration. And even then, it's safest to provide the minimal self-sustaining content. Also, in my opinion, the rule should be "the one who provided the link is the one responsible for maintaining its validity".
edited to quote the relevant description and example from docs
0

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());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.