如何定义由一个域组成的多个域的D3标尺?
示例
在此示例中,我有3个大小不同的域,我希望它们转换为相等范围的三分之一。
我想做什么:
const yScale = linearScale()
.domain([ [0, 10], [11, 50], [51, 500] ])
.range([0, 100])
我目前正在做什么:
const yScale1 = linearScale().domain([0, 10]).range([0, 33]);
const yScale2 = linearScale().domain([11, 50]).range([34, 66]);
const yScale3 = linearScale().domain([51, 500]).range([67, 100]);
if (val > 51) {
return yScale3(val);
} else if (val > 11) {
return yScale2(val);
} else {
return yScale1(val);
}
答案 0 :(得分:2)
D3线性刻度允许您传递域和范围的多个值。如API中所述:
尽管连续刻度通常在其域和范围中每个都有两个值,但指定两个以上的值会产生分段刻度。
您的情况是:
const scale = d3.scaleLinear()
.domain([0,10,50,500])
.range([0, 33.3, 66.6, 100]);
或者,使用D3 v5.8速记的单行代码:
const scale = d3.scaleLinear([0,10,50,500], [0, 33.3, 66.6, 100]);
让我们看看它的作用:
const svg = d3.select("svg");
const scale = d3.scaleLinear()
.domain([0, 10, 50, 500])
.range([0, 33.3, 66.6, 100]);
const circles = svg.selectAll(null)
.data(d3.range(0, 500, 2))
.enter()
.append("circle")
.attr("r", 2)
.attr("cx", (_, i) => 5 + i * 2 + 1)
.attr("cy", d => 105 - scale(d));
svg {
background-color: wheat;
}
circle {
fill: none;
stroke: gray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="510" height="110"></svg>
当然,更好的做法是根据域中元素的数量动态创建范围:
const scale = d3.scaleLinear()
.domain([0, 10, 50, 500]);
scale.range(d3.range(0, 100 + 100 / (scale.domain().length - 1), 100 / (scale.domain().length - 1)))
console.log(scale.range())
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>