javascript 从 svg 外部的按钮单击 d3 中的节点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11206015/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
clicking a node in d3 from a button outside the svg
提问by Rahul Rout
I have created a force directed graph using D3 and displayed the id of the nodes in a normal div. I need to highlight the node whose id has been clicked in the div. I have searched the id of the node and using normal javascript tried to click it but it does not work.
我使用 D3 创建了一个力有向图,并在普通 div 中显示了节点的 id。我需要在 div 中突出显示其 id 已被单击的节点。我搜索了节点的 id 并使用普通的 javascript 尝试单击它,但它不起作用。
回答by mbostock
More generally, if the user interacts with element A, how do you select (and then modify) related elements B? There are many ways of achieving this, but here are three common approaches.
更一般地,如果用户与元素A交互,您如何选择(然后修改)相关元素B?有很多方法可以实现这一点,但这里有三种常见的方法。
Option 1. For one-to-one mappings, select by id.
选项 1. 对于一对一映射,按 id 选择。
If each element in Ahas exactly one corresponding element in B, you can select the related element B by id, such as d3.select("#foo")
to select a <div id="foo">
.
如果在每个元件阿具有恰好一个对应元件乙,可以通过ID选择相关的元件B,如d3.select("#foo")
选择一个<div id="foo">
。
This approach requires setting an id for each element in Busing selection.attr. This is easiest if your data has an intrinsic unique identifier, such as d.name
or d.id
:
这种方法需要使用selection.attr为B 中的每个元素设置一个 id 。如果您的数据具有固有的唯一标识符,则这是最简单的,例如或:d.name
d.id
b.attr("id", function(d) { return d.id; });
Next, to enable clicking on elements Ato change the fill color of the corresponding element in B, use selection.onto register a click listener, and then select by id:
接下来,要启用点击元素A来改变B 中对应元素的填充颜色,使用selection.on注册一个点击监听器,然后通过 id 选择:
a.on("click", function(d) {
d3.select("#" + d.id).style("fill", "red");
});
Identifiers must be both unique and valid. For example, the id must start with a letter and not a number, and can't contain spaces. If your data doesn't already have a unique identifier, you could generate one from the index, such as
标识符必须是唯一且有效的。例如,id 必须以字母而不是数字开头,并且不能包含空格。如果您的数据还没有唯一标识符,您可以从索引中生成一个,例如
b.attr("id", function(d, i) { return "b-" + i; });
And later, assuming the elements Aare in the same order,
然后,假设元素A的顺序相同,
a.on("click", function(d, i) {
d3.select("#b-" + i).style("fill", "red");
});
You could also iterate over your data arrayto generate a unique identifier.
您还可以遍历数据数组以生成唯一标识符。
Option 2. For one-to-many mappings, select by class.
选项 2. 对于一对多映射,按类选择。
To select elements of class "foo", such as a <div class="foo">
, say d3.selectAll(".foo")
. Use this approach if any element in Acorresponds to multiple elements in B. For example, if you had a force-directed graph showing the relationships between students, you might color the nodes based on each student's year, and then use a legend to toggle the visibility of each year.
要选择“foo”类的元素,例如 a <div class="foo">
,比如d3.selectAll(".foo")
。如果A 中的任何元素对应于B 中的多个元素,请使用此方法。例如,如果您有一个显示学生之间关系的力导向图,您可以根据每个学生的年份为节点着色,然后使用图例来切换每年的可见性。
As with the previous approach, you can use selection.attrto set the "class" attribute. In this case, the class attribute is not unique, so it might come from a d.type
property in the data:
与之前的方法一样,您可以使用selection.attr来设置“class”属性。在这种情况下,类属性不是唯一的,因此它可能来自d.type
数据中的属性:
b.attr("class", function(d) { return d.type; })
If you have multiple legends for different categorical attributes of data, you could also be more specific and prefix the class name. To continue the student year example:
如果您有数据的不同分类属性的多个图例,您也可以更具体并在类名前加上前缀。继续以学生年为例:
b.attr("class", function(d) { return "year-" + d.year; })
Setting the class attribute will replace any previously-set classes, so if you want to apply multiple classes to the elements, you need to join them together with a space when setting the "class" attribute.
设置 class 属性将替换任何先前设置的类,因此如果您想将多个类应用于元素,则需要在设置“class”属性时将它们连接在一起,并用空格将它们连接在一起。
Next, to enable clicking on elements Ato change the fill color of the corresponding elements in B, use selection.on to register a click listener, and then select by class:
接下来,要启用点击元素A以更改B 中相应元素的填充颜色,请使用 selection.on 注册一个点击侦听器,然后按类进行选择:
a.on("click", function(d) {
d3.selectAll("." + d.type).style("fill", "red");
});
Note that we're using selectAllhere rather than select; that's because we want to select all corresponding elements, rather than just the first one. Again, you'll need to make sure that the class attribute is valid.
请注意,我们在这里使用的是selectAll而不是select;那是因为我们要选择所有相应的元素,而不仅仅是第一个。同样,您需要确保 class 属性有效。
Option 3. For everything else, select and filter by data.
选项 3. 对于其他所有内容,请按数据选择和过滤。
The previous two approaches generate ids and classes so that the browser can index the elements in Bfor efficient selection. For a small number of elements, or when more general selection methods are needed, you can omit specifying "id" or "class" attributes and simply select manually by selection.filter.
前两种方法生成 id 和类,以便浏览器可以索引B 中的元素以进行高效选择。对于少量元素,或者需要更通用的选择方法时,可以省略指定“id”或“class”属性,只需通过selection.filter手动选择。
Let's call the datum associated with each element in Ada
, and the datum associated with each element in Bdb
. Now all we have to do is define an expression that returns true when da
matches db
. For example, if we wanted to filter by type:
让我们调用与Ada
中每个元素关联的数据,以及与B 中每个元素关联的数据db
。现在我们要做的就是定义一个表达式,当da
匹配时返回真db
。例如,如果我们想按类型过滤:
a.on("click", function(da) {
b.filter(function(db) { return da.type == db.type; }).style("fill", "red");
});
The first two options are preferred, but occasionally manual filtering is useful, such as when you have a range slider and want to filter based on a quantitative variable.
首选前两个选项,但有时手动过滤很有用,例如当您有一个范围滑块并希望基于定量变量进行过滤时。
回答by Phrogz
When you write:
当你写:
…and using normal javascript tried to click it…
…并使用普通的javascript尝试点击它…
what do you mean?
你是什么意思?
If you mean that you wrote code like:
如果您的意思是您编写的代码如下:
mySVGElement.click();
then that is your problem. Not all DOM elements have a click()
method like a <button>
or <input…>
may. Instead, you need to simulate and fire your own click event:
那就是你的问题。并非所有 DOM 元素都具有click()
类似 a<button>
或<input…>
may的方法。相反,您需要模拟并触发您自己的点击事件:
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
}