Как отметил @FelixKling, наиболее вероятным сценарием является то, что узлы, которые вы ищете, еще не существуют.
Однако современные методы разработки часто могут манипулировать элементами документа за пределами дерева документов либо с DocumentFragments, либо просто отсоединением / повторным подключением текущих элементов напрямую. Такие методы могут использоваться как часть шаблонов JavaScript или для предотвращения чрезмерных операций перерисовки / переплавки, в то время как элементы, о которых идет речь, сильно изменяются.
Аналогично, новая функциональность «Теневой DOM» развертывается в современных браузерах позволяет элементам быть частью документа, но не обрабатываться запросом document.getElementById и всеми его методами sibling (querySelector и т. д.). Это делается для инкапсуляции функциональных возможностей и, в частности, скрыть его.
Опять же, скорее всего, элемент, который вы ищете, просто (пока) в документе, и вы должны сделать, как предлагает Феликс , Тем не менее, вы также должны знать, что это все чаще является не единственной причиной того, что элемент может быть необоснованным (временно или постоянно).
Проблема с вашим кодом заключается в том, что вы пытаетесь использовать значения из вашего массива data
для создания диапазонов диапазонов в порядковой шкале. Поскольку одно и то же входное значение всегда будет сопоставлено с тем же выходным значением, что означает, что оба входа 16
отображаются в один диапазон диапазона 72
.
Если вы хотите, чтобы каждое входное значение отображалось на его собственный «бар», тогда вам нужно использовать индексы массива вместо значений массива.
Сначала вы готовите индексы
var indices = d3.range(0, data.length); // [0, 1, 2, ..., data.length-1]
Затем вы используете их для определения шкалы y
domain
var y = d3.scale.ordinal()
.domain(indices)
// use rangeRoundBands instead of rangeBands when your output units
// are pixels (or integers) if you want to avoid empty line artifacts
.rangeRoundBands([0, chartHeight]);
Наконец, вместо использования значений массива в качестве входных данных используются индексы массивов при сопоставлении с y
chart.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("y", function (value, index) {
// use the index as input instead of value; y(index) instead of y(value)
return y(index);
})
.attr("width", x)
.attr("height", y.rangeBand());
. В качестве дополнительного бонуса этот код автоматически изменит масштаб диаграммы если количество данных изменяется или вы решите изменить ширину или высоту диаграммы.
Вот демон jsFiddle: http://jsfiddle.net/q8SBN/1/
Полный код:
var data = [4, 8, 15, 16, 23, 16];
var indices = d3.range(0, data.length);
var chartWidth = 420;
var chartHeight = 120;
var chart = d3.select("body").append("svg")
.attr("class", "chart")
.attr("width", chartWidth)
.attr("height", chartHeight);
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, chartWidth])
var y = d3.scale.ordinal()
.domain(indices)
.rangeRoundBands([0, chartHeight]);
chart.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("y", function (value, index) { return y(index); })
.attr("width", x)
.attr("height", y.rangeBand());
Способ установки атрибута y
для прямоугольников будет использовать одинаковое значение для всех повторяющихся элементов. Вы можете использовать некоторые смещения так:
chart.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("y", function (d, i) {
return (i * y.rangeBand()) + y.rangeBand();})
.attr("width", x)
.attr("height", y.rangeBand());
Также вам, возможно, придется настроить высоту вашей общей диаграммы, чтобы увидеть все полосы.