#d3.js
#d3.js
Вопрос:
Как я могу определить шкалу 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);
}
Ответ №1:
Линейные шкалы D3 позволяют передавать несколько значений как для домена, так и для диапазона. Как описано в API:
Хотя непрерывные шкалы обычно имеют по два значения каждая в своем домене и диапазоне, указание более двух значений приводит к кусочному масштабированию.
В вашем случае это были бы:
const scale = d3.scaleLinear()
.domain([0,10,50,500])
.range([0, 33.3, 66.6, 100]);
В качестве альтернативы, однострочный вариант с использованием сокращений D3 версии 5.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>