Я пытаюсь изменить карту Бостока США по безработице, которая применяет хроматическую шкалу D3.
Теперь я могу изменить размеры ковша, как мне представляется, для построения моих данных, однако, когда я это делаю, легенда, кажется, растет в геометрической прогрессии, и я не могу сделать ее пригодной к желаемой ширине и соответствующим образом масштабировать интервалы.
Пожалуйста, ознакомьтесь с прилагаемым jsfiddle, где я продемонстрирую возникшую проблему. Я хотел бы изменить легенду двумя способами:
Моя проблема в том, что я, кажется, не в состоянии изменить параметры в следующей строке кода (я надеюсь, что это не значение по умолчанию в хроматическом сценарии масштаба).
g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(function(x, i) { return i ? x : x + "%"; })
.tickValues(color.domain()))
.select(".domain")
.remove();
В коде есть только две проблемы, которые легко исправить.
Первая проблема - это домен:
var myDomain = [1, 5, 8, 9, 12, 18, 20, 25]
var x = d3.scaleLinear()
.domain(myDomain)
.rangeRound([600, 860]);
Как вы можете видеть, вы передаете массив с несколькими значениями. Однако для линейного масштаба с двумя значениями в диапазоне вам нужно передать массив с двумя значениями.
Следовательно, это должно быть:
var myDomain = [1, 5, 8, 9, 12, 18, 20, 25]
var x = d3.scaleLinear()
.domain(d3.extent(myDomain))//just two values here
.rangeRound([600, 860]);
Вторая проблема здесь:
if (d[1] == null) d[1] = x.domain()[1];
//this is the second element -------^
Поскольку myDomain
- это массив с несколькими значениями, вы передаете второе значение здесь. Но вы не хотите второго значения, вы хотите получить последнее значение.
Следовательно, это должно быть:
if (d[1] == null) d[1] = x.domain()[x.domain().length - 1];
//now this is the last element --------------^
Вот код с этими изменениями (я удалил карту, мы не нуждаемся в ней для этого ответа, а также переместили легенду влево, чтобы она лучше соответствовала SO snippet):
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var myDomain = [1, 5, 8, 9, 12, 18, 20, 25]
var x = d3.scaleLinear()
.domain(d3.extent(myDomain))
.rangeRound([200, 460]);
var color = d3.scaleThreshold()
.domain(myDomain)
.range(d3.schemeBlues[9]);
var g = svg.append("g")
.attr("class", "key");
g.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
if (d[0] == null) d[0] = x.domain()[0];
if (d[1] == null) d[1] = x.domain()[x.domain().length - 1];
return d;
}))
.enter().append("rect")
.attr("height", 8)
.attr("x", function(d) { return x(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
.attr("fill", function(d) { return color(d[0]); });
g.append("text")
.attr("class", "caption")
.attr("x", x.range()[0])
.attr("y", -6)
.attr("fill", "#000")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text("Unemployment rate");
g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(function(x, i) { return i ? x : x + "%"; })
.tickValues(color.domain()))
.select(".domain")
.remove();
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<svg width="600" height="200"></svg>