问题
I'm building a heat map with a color gradient from green to red. I want cells with value 0
to be green, and values greater or equal than 1
to take the other colors.
I'm building the scale this way :
var colors = [
'#27C24C',
'#7DB22E',
'#D4A10F',
'#F97C20',
'#F35F40',
'#FF0000'
];
var colorScale = d3.scale.quantile()
.domain([0, d3.max(data, function (d) { return d.value; })])
.range(colors);
But this returns me the following quantiles :
[239.16666666666677, 478.3333333333332, 717.5, 956.6666666666664, 1195.8333333333335]
Therefore, I have the following heatmap :
But I would like the pointed cell to be the second shade of green, since its value is strictly greater than 0
.
回答1:
You cannot use only quantile scale in this case. Write custom scale function to treat the zero value separately.
var colors = [
// '#27C24C', this value must not be included in the internal range
'#7DB22E',
'#D4A10F',
'#F97C20',
'#F35F40',
'#FF0000'
];
var colorScaleInternal = d3.scale.quantile()
.domain([0, d3.max(data, function (d) { return d.value; })])
.range(colors);
var colorScale = function(value) {
return !!value ? colorScaleInternal(value) : '#27C24C';
};
回答2:
While I couldn't find support in D3 for this functionality, I was able to work around it by altering the range array sent to d3. The idea is to check with D3 if the quartiles are repeating, and if so, keep the same color for all of them:
var scale = d3.scale.quantile().domain(domain).range(range);
var quantiles = scale.quantiles();
quantiles.unshift(d3.min(domain));
// Now that you have the quantiles, you can see if some of them are holding the same value,
// and it that case set the minimum value to all of them.
var modifiedRange = [range[0]];
for (var i = 1; i < range.length; i++) {
if (quantiles[i] === quantiles[i - 1]) {
modifiedRange.push(modifiedRange[i - 1]);
} else {
modifiedRange.push(range[i]);
}
}
// set the new scale
scale.range(modifiedRange);
来源:https://stackoverflow.com/questions/35457643/d3-quantile-scale-force-first-quantile