Подтвердить что ты не робот

Выбор фильтра d3 не работает?

Либо я не использую d3 selection.filter правильно, либо он глючит. Я могу перевести проблему на несколько строк. Я нахожусь в отладчике Chrome с загруженным d3. Пусть начинается пустой выбор

d3.selectAll("nonexistant").empty()
> true

и привязать к нему некоторые данные.

d3.selectAll("nonexistant").data([1,2,3,4])
> [Array[4]]

Хорошо, поэтому он имеет размер четыре. Позвольте проверить с помощью selection.size:

d3.selectAll("nonexistant").data([1,2,3,4]).size()
> 0

Я думаю, что, поскольку нет элементов DOM еще, выбор обновления пуст, поскольку ранее не было элементов. Поэтому давайте make получить доступ к выбору ввода.

d3.selectAll("nonexistant").data([1,2,3,4]).enter()
> [Array[4]]
d3.selectAll("nonexistant").data([1,2,3,4]).enter().size()
> TypeError: undefined is not a function
d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").size()
> 4

Не уверен, почему выбор ввода вызывает ошибку, (UPDATE: Fixed in v3.4.12), но в любом случае, если мы попытаемся выполнить фильтрацию с помощью функции example в документах,

function odds(d, i) { return i & 1; }
d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds);
> [Array[0]]
d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds);
> []
d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").filter(odds)
> [Array[2]]

Почему это тихо отфильтровывает все элементы, когда нет связанных элементов DOM? Кажется, он работает, когда у меня уже есть элементы DOM. Но это кажется бесполезным, поскольку я не хочу создавать элементы для данных, которые я отбрасываю. Может быть, если я ставил фильтр раньше?

d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds).enter().append("p").size()
> TypeError: undefined is not a function
d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds).append("p").size()
> TypeError: undefined is not a function

Неа. Кажется, что это путь с родным JS filter на массивах:

d3.selectAll("nonexistant").data([1,2,3,4].filter(odds)).enter().append("p").size()
> 2

Документы d3, похоже, не различают выбор, которые связаны с элементами DOM, и те, которые этого не делают. Кажется, что я должен иметь возможность привязать filter к любой цепочке методов (и вызвать size для любого выбора) и получить правильный результат без ошибки типа. Конечно, filter также поддерживает селектор CSS, для которого требуются элементы DOM, но я не использую их здесь.

Что я хочу знать: существует несоответствие между тем, что делает d3, и тем, что я ожидаю. В какой степени я упускаю из виду неправильные представления о выборах и какие операции действуют на них? В какой степени документация неясна? Любое из этого поведения квалифицируется как ошибка?

4b9b3361

Ответ 1

Из документация метода .enter():

... выбор ввода определяет только операторы append, insert, select и call; вы должны использовать эти операторы для создания экземпляров входящих узлов перед изменением любого содержимого. (Введите флажки, также поддерживающие empty, чтобы проверить, пусты ли они.)

Вызов чего-либо другого не дает полезных результатов. Является ли это ошибкой, побочным эффектом или функцией, возможно, спорным. Почти во всех случаях он не создает никаких барьеров, за исключением, может быть, если вам нужно знать этот выбор size(), чтобы узнать, сколько данных из массива, которое вы передаете в data(), еще не создавали элементы.

Как только вы назовёте append() в выборе ввода, это ведет себя хорошо, как и любой обычный выбор. Фактически, append() возвращает новый выбор, поэтому он !== возвращает значение enter().

Это, когда вы также можете проверить size() этого выбора, так что это действительно считается только проблемой, если вам нужно знать размер PRIOR для вызова append().

Вы правы, что использование собственного массива filter является решением, если вам не нужно даже добавлять элементы, где odds(d) == false.

Фильтр полезен, если вы уже создали узлы DOM (например, <p> s), привязанные к [1,2,3,4] и (например, в обработчике событий, когда пользователь нажимает кнопку "выделить все шансы" ), вы вызов

d3.selectAll('p').filter(odds).css('color', 'red')

Кстати, это был действительно хорошо написанный вопрос.