D3:如何创建自定义的倾斜色标?
D3: How to create a custom, skewed color scale?
我创建了以下色标:
代码如下:
function continuous(selector_id, colorscale) {
var legendheight = 200,
legendwidth = 80,
margin = { top: 10, right: 60, bottom: 10, left: 2 };
var canvas = d3
.select(selector_id)
.style("height", legendheight + "px")
.style("width", legendwidth + "px")
.style("position", "relative")
.append("canvas")
.attr("height", legendheight - margin.top - margin.bottom)
.attr("width", 1)
.style("height", legendheight - margin.top - margin.bottom + "px")
.style("width", legendwidth - margin.left - margin.right + "px")
.style("border", "1px solid #000")
.style("position", "absolute")
.style("top", margin.top + "px")
.style("left", margin.left + "px")
.node();
var ctx = canvas.getContext("2d");
var legendscale = d3
.scaleLinear()
.range([1, legendheight - margin.top - margin.bottom])
.domain(colorscale.domain());
var image = ctx.createImageData(1, legendheight);
d3.range(legendheight).forEach(function (i) {
var c = d3.rgb(colorscale(legendscale.invert(i)));
image.data[4 * i] = c.r;
image.data[4 * i + 1] = c.g;
image.data[4 * i + 2] = c.b;
image.data[4 * i + 3] = 255;
});
ctx.putImageData(image, 0, 0);
var legendaxis = d3.axisRight().scale(legendscale).tickSize(6).ticks(8);
var svg = d3
.select(selector_id)
.append("svg")
.attr("height", legendheight + "px")
.attr("width", legendwidth + "px")
.style("position", "absolute")
.style("left", "0px")
.style("top", "0px");
svg
.append("g")
.attr("class", "axis")
.attr(
"transform",
"translate(" +
(legendwidth - margin.left - margin.right + 3) +
"," +
margin.top +
")"
)
.call(legendaxis);
}
useEffect(() => {
var colorScale = d3.scaleSequential(d3.interpolateRdYlGn).domain([-4, 16]);
var svg = continuous("#legend1", colorScale);
}, []);
由于我的数据偏向于大于 0 的值,我想创建一个自定义比例,其中偏斜的红色到绿色着色和发生在 0
而不是 6
的过渡。但是,我在实现自定义缩放功能时遇到了问题。
我遵循了 post 的建议,但无法实现功能,即:
var custom = d3.scaleLinear()
.domain([0, 50, 90, 95, 100])
.range(['#edfc1b','#ec6f3b','#bc2e67','#7c0093', '#0b0074']);
目前,我从上面的代码中得到的是:
所以,我的问题是:如果我有一个值数组,例如 [0, 50, 90, 95, 100]
?
,我怎样才能绘制出完整的域?
或者,是否有更好的方法在 D3 中创建自定义色标?
定义比例的代码是正确的:
var custom = d3.scaleLinear()
.domain([0, 50, 90, 95, 100])
.range(['#edfc1b','#ec6f3b','#bc2e67','#7c0093', '#0b0074']);
问题在于将此颜色比例转换为空间比例的代码:
var legendscale = d3
.scaleLinear()
.range([1, legendheight - margin.top - margin.bottom])
.domain(colorscale.domain())
上面的代码创建了一个范围长度为2,域长度为5的比例尺。scaleLinear
需要域和范围长度相等的数组,否则不会做1 -to-1 映射如预期。
当域的长度固定(在您的情况下为 5)时,一个快速修复方法是通过中间步骤手动扩展范围。
var max = legendheight - margin.top - margin.bottom;
var legendscale = d3
.scaleLinear()
.range([1, max / 4, 2*(max / 4), 3*(max / 4), max])
.domain(colorscale.domain())
我创建了以下色标:
代码如下:
function continuous(selector_id, colorscale) {
var legendheight = 200,
legendwidth = 80,
margin = { top: 10, right: 60, bottom: 10, left: 2 };
var canvas = d3
.select(selector_id)
.style("height", legendheight + "px")
.style("width", legendwidth + "px")
.style("position", "relative")
.append("canvas")
.attr("height", legendheight - margin.top - margin.bottom)
.attr("width", 1)
.style("height", legendheight - margin.top - margin.bottom + "px")
.style("width", legendwidth - margin.left - margin.right + "px")
.style("border", "1px solid #000")
.style("position", "absolute")
.style("top", margin.top + "px")
.style("left", margin.left + "px")
.node();
var ctx = canvas.getContext("2d");
var legendscale = d3
.scaleLinear()
.range([1, legendheight - margin.top - margin.bottom])
.domain(colorscale.domain());
var image = ctx.createImageData(1, legendheight);
d3.range(legendheight).forEach(function (i) {
var c = d3.rgb(colorscale(legendscale.invert(i)));
image.data[4 * i] = c.r;
image.data[4 * i + 1] = c.g;
image.data[4 * i + 2] = c.b;
image.data[4 * i + 3] = 255;
});
ctx.putImageData(image, 0, 0);
var legendaxis = d3.axisRight().scale(legendscale).tickSize(6).ticks(8);
var svg = d3
.select(selector_id)
.append("svg")
.attr("height", legendheight + "px")
.attr("width", legendwidth + "px")
.style("position", "absolute")
.style("left", "0px")
.style("top", "0px");
svg
.append("g")
.attr("class", "axis")
.attr(
"transform",
"translate(" +
(legendwidth - margin.left - margin.right + 3) +
"," +
margin.top +
")"
)
.call(legendaxis);
}
useEffect(() => {
var colorScale = d3.scaleSequential(d3.interpolateRdYlGn).domain([-4, 16]);
var svg = continuous("#legend1", colorScale);
}, []);
由于我的数据偏向于大于 0 的值,我想创建一个自定义比例,其中偏斜的红色到绿色着色和发生在 0
而不是 6
的过渡。但是,我在实现自定义缩放功能时遇到了问题。
我遵循了
var custom = d3.scaleLinear()
.domain([0, 50, 90, 95, 100])
.range(['#edfc1b','#ec6f3b','#bc2e67','#7c0093', '#0b0074']);
目前,我从上面的代码中得到的是:
所以,我的问题是:如果我有一个值数组,例如 [0, 50, 90, 95, 100]
?
或者,是否有更好的方法在 D3 中创建自定义色标?
定义比例的代码是正确的:
var custom = d3.scaleLinear()
.domain([0, 50, 90, 95, 100])
.range(['#edfc1b','#ec6f3b','#bc2e67','#7c0093', '#0b0074']);
问题在于将此颜色比例转换为空间比例的代码:
var legendscale = d3
.scaleLinear()
.range([1, legendheight - margin.top - margin.bottom])
.domain(colorscale.domain())
上面的代码创建了一个范围长度为2,域长度为5的比例尺。scaleLinear
需要域和范围长度相等的数组,否则不会做1 -to-1 映射如预期。
当域的长度固定(在您的情况下为 5)时,一个快速修复方法是通过中间步骤手动扩展范围。
var max = legendheight - margin.top - margin.bottom;
var legendscale = d3
.scaleLinear()
.range([1, max / 4, 2*(max / 4), 3*(max / 4), max])
.domain(colorscale.domain())