Я создал граф, ориентированный на силу, используя D3 и отображающий идентификатор узлов в нормальном div. Мне нужно выделить node, идентификатор которого был нажат в div. Я искал идентификатор node и, используя обычный javascript, пытался щелкнуть его, но он не работает.
Нажав кнопку node в d3 с кнопки за пределами svg
Ответ 1
В общем случае, если пользователь взаимодействует с элементом A, как вы выбираете (а затем модифицируете) связанные элементы B? Существует много способов достижения этого, но здесь есть три общих подхода.
Вариант 1. Для взаимно-однозначных сопоставлений выберите по id.
Если каждый элемент в имеет ровно один соответствующий элемент в B, вы можете выбрать связанный элемент B по id, например d3.select("#foo")
, чтобы выбрать <div id="foo">
.
Этот подход требует установки идентификатора для каждого элемента в B с помощью selection.attr. Это проще всего, если ваши данные имеют встроенный уникальный идентификатор, например d.name
или d.id
:
b.attr("id", function(d) { return d.id; });
Затем, чтобы включить щелчок по элементам A, чтобы изменить цвет заливки соответствующего элемента в B, используйте selection.on, чтобы зарегистрировать нажмите кнопку прослушивания, а затем выберите по id:
a.on("click", function(d) {
d3.select("#" + d.id).style("fill", "red");
});
Идентификаторы должны быть уникальными и valid. Например, идентификатор должен начинаться с буквы, а не числа, и не может содержать пробелов. Если ваши данные еще не имеют уникального идентификатора, вы можете создать его из индекса, например
b.attr("id", function(d, i) { return "b-" + i; });
И позже, предполагая, что элементы A находятся в одном порядке,
a.on("click", function(d, i) {
d3.select("#b-" + i).style("fill", "red");
});
Вы также можете перебирать свой массив данных для создания уникального идентификатора.
Вариант 2. Для сопоставлений "один ко многим" выберите по классу.
Чтобы выбрать элементы класса "foo", такие как <div class="foo">
, скажем d3.selectAll(".foo")
. Используйте этот подход, если какой-либо элемент из A соответствует нескольким элементам в B. Например, если у вас есть ориентированный на силу график, показывающий отношения между учениками, вы можете покрасить узлы на основе каждого студенческого года, а затем использовать легенду для переключения видимость каждого года.
Как и в предыдущем подходе, вы можете использовать selection.attr, чтобы установить атрибут "class". В этом случае атрибут класса не является уникальным, поэтому он может исходить из свойства d.type
в данных:
b.attr("class", function(d) { return d.type; })
Если у вас несколько легенд для разных категориальных атрибутов данных, вы также можете быть более конкретными и префикс имени класса. Чтобы продолжить пример студенческого года:
b.attr("class", function(d) { return "year-" + d.year; })
Установка атрибута класса заменит все ранее установленные классы, поэтому, если вы хотите применить несколько классов к элементам, вам нужно объединить их вместе с пробелом при установке атрибута class.
Затем, чтобы включить щелчок по элементам A, чтобы изменить цвет заливки соответствующих элементов в B, используйте selection.on, чтобы зарегистрировать прослушиватель кликов, а затем выберите по классу:
a.on("click", function(d) {
d3.selectAll("." + d.type).style("fill", "red");
});
Обратите внимание, что здесь мы используем selectAll вместо select; потому что мы хотим выбрать все соответствующие элементы, а не только первую. Опять же, вам нужно убедиться, что атрибут класса valid.
Вариант 3. Для всего остального выберите и фильтруйте данные.
Предыдущие два подхода генерируют идентификаторы и классы, чтобы браузер мог индексировать элементы в B для эффективного выбора. Для небольшого количества элементов или когда требуются более общие методы выбора, вы можете опустить указание атрибутов "id" или "class" и просто выбрать вручную selection.filter.
Позвольте назвать привязку, связанную с каждым элементом в da
, и привязку к каждому элементу в B db
. Теперь все, что нам нужно сделать, это определить выражение, которое возвращает true, когда da
соответствует db
. Например, если мы хотим отфильтровать по типу:
a.on("click", function(da) {
b.filter(function(db) { return da.type == db.type; }).style("fill", "red");
});
Предпочтительны первые два варианта, но иногда удобна ручная фильтрация, например, когда у вас есть ползунок диапазона и вы хотите фильтровать на основе количественной переменной.
Ответ 2
Когда вы пишете:
... и с помощью обычного javascript попытался щелкнуть его...
что вы имеете в виду?
Если вы имеете в виду, что вы написали код вроде:
mySVGElement.click();
то это ваша проблема. Не все элементы DOM имеют метод click()
, такой как <button>
или <input…>
. Вместо этого вам нужно имитировать и запустить собственное событие click:
function simulateClick(elementToClick){
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var canceled = !elementToClick.dispatchEvent(evt);
return canceled; //Indicate if `preventDefault` was called during handling
}