从svg外部的按钮单击d3中的节点 [英] clicking a node in d3 from a button outside the svg

查看:274
本文介绍了从svg外部的按钮单击d3中的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用D3创建了一个力有向图,并在正常的div中显示了节点的id。我需要突出显示其ID已在div中被点击的节点。
我搜索了该节点的id,并使用正常的javascript尝试点击它但它不工作。

解决方案

更一般来说,如果用户与元素 A 交互,如何选择(然后修改)相关元素 B ?有很多方法可以实现这一点,但是这里有三种常见的方法。



选项1.对于一对一映射,按id选择



如果 A 中的每个元素在 B 中只有一个对应的元素,您可以通过id选择相关的元素B, code> d3.select(#foo)选择< div id =foo> p>

此方法需要使用 B 中每个元素的ID / Selections#wiki-attrrel =noreferrer> selection.attr 。如果您的数据具有固有的唯一标识符,例如 d.name d.id

  b.attr(id,function(d){return d.id;}); 

接下来,要启用点击元素 A 以更改填充颜色 中的相应元素,请使用 selection.on a>注册一个点击监听器,然后通过id选择:

  a.on {
d3.select(#+ d.id).style(fill,red);
});

标识符必须都是唯一的,并且有效 。例如,id必须以字母开头,而不是数字,且不能包含空格。如果您的数据没有唯一的标识符,您可以从索引生成一个,例如

  b.attr id,function(d,i){returnb-+ i;}); 

稍后,假设元素 A / p>

  a.on(click,function(d,i){
d3.select(#b- + i).style(fill,red);
});

您也可以遍历您的数据数组以生成唯一标识符。





选择类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){returnyear- d.year;})

设置类属性将替换任何先前设置的类,想要对元素应用多个类,您需要在设置类属性时使用空格连接它们。



接下来,要启用元素 > A 以更改 B 中相应元素的填充颜色,请使用selection.on注册点击监听器,然后按类别进行选择:

  a.on(click,function(d){
d3.selectAll(。+ d.type).style ,red);
});

请注意,我们使用 selectAll ,而不是选择;这是因为我们要选择所有相应的元素,而不仅仅是第一个元素。同样,您需要确保类属性为 valid



选项3.对于其他选项,请按数据选择并过滤。



方法生成ids和类,以便浏览器可以索引 B 中的元素以进行有效的选择。对于少数元素,或需要更一般的选择方法时,您可以省略指定id或class属性,只需手动选择 selection.filter



让我们调用与 A中每个元素相关的基准 da 以及与 B db 中的每个元素相关联的基准。现在我们要做的是定义一个表达式,当 da 匹配 db 时返回true。例如,如果我们要按类型过滤:

  a.on(click,function(da){
b.filter(function(db){return da.type == db.type;})style(fill,red);
});

前两个选项是首选,但偶尔手动过滤很有用,例如,滑块,并希望根据定量变量进行过滤。


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.

解决方案

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.

Option 1. For one-to-one mappings, select by id.

If each element in A has 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">.

This approach requires setting an id for each element in B using selection.attr. This is easiest if your data has an intrinsic unique identifier, such as d.name or d.id:

b.attr("id", function(d) { return d.id; });

Next, to enable clicking on elements A to change the fill color of the corresponding element in B, use selection.on to register a click listener, and then select by 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

b.attr("id", function(d, i) { return "b-" + i; });

And later, assuming the elements A are in the same order,

a.on("click", function(d, i) {
  d3.select("#b-" + i).style("fill", "red");
});

You could also iterate over your data array to generate a unique identifier.

Option 2. For one-to-many mappings, select by class.

To select elements of class "foo", such as a <div class="foo">, say d3.selectAll(".foo"). Use this approach if any element in A corresponds 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.

As with the previous approach, you can use selection.attr to 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:

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.

Next, to enable clicking on elements A to change the fill color of the corresponding elements in B, use selection.on to register a click listener, and then select by class:

a.on("click", function(d) {
  d3.selectAll("." + d.type).style("fill", "red");
});

Note that we're using selectAll here 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.

Option 3. For everything else, select and filter by data.

The previous two approaches generate ids and classes so that the browser can index the elements in B for 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.

Let's call the datum associated with each element in A da, and the datum associated with each element in B db. 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:

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.

这篇关于从svg外部的按钮单击d3中的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆