d3.js - 将多个鼠标悬停事件应用于相邻(连接)节点

标签 d3.js mouseover highlight force-layout

我有一个网络图(力导向图)、一个散点图和一个相互关联的表格(参见 jsFiddle)。我让互连按照我希望它们用于鼠标悬停事件的方式工作。我想修改我的代码,以便当我将鼠标悬停在网络图中的节点上时,不仅突出显示鼠标悬停的节点(及其在散点图和表格中的连接),而且突出显示其直接相邻节点(以及作为它们在散点图和表格中的连接)。

我查看了Highlight selected node, its links, and its children in a D3 force directed graph中的信息求助。一路上的某个地方(不确定在哪里),我发现了一个帮助定义连接节点的函数示例,isConnected() .

function isConnected(a, b) {
    return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index;
    }

我想将此功能合并到我的鼠标悬停事件中,也许使用 if()声明,以便我可以做我想要的所有“突出显示”。但是,我是 D3 和 js 的新手,不确定如何设置。

下面是我想修改的代码片段(来自 jsFiddle )。我将不胜感激任何建议或指向其他示例的指针。
var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("g")
    .attr("class", function(d) { return "node " + d.name + " " + d.location; })
    .call(force.drag)
    .on("mouseover", function(d) { 
        // I would like to insert an if statement to do all of these things to the connected nodes
        // if(isConnected(d, o)) {
            d3.select(this).select("circle").style("stroke-width", 6); 
            d3.select(this).select("circle").style("stroke", "orange"); 
            d3.select(this).select("text").style("font", "20px sans-serif");
            d3.selectAll("rect." + d.location).style("stroke-width", 6);
            d3.selectAll("rect." + d.location).style("stroke", "orange");
            d3.selectAll("text." + d.location).style("font", "20px sans-serif");
            d3.selectAll("tr." + d.name).style("background-color", "orange");
            //}
        })
    .on("mouseout",  function(d) { 
        // if(isConnected(d, o)) {
            d3.select(this).select("circle").style("stroke-width", 1.5); 
            d3.select(this).select("circle").style("stroke", "gray"); 
            d3.select(this).select("text").style("font", "12px sans-serif");
            d3.selectAll("rect." + d.location).style("stroke-width", 1.5);
            d3.selectAll("rect." + d.location).style("stroke", "gray");
            d3.selectAll("text." + d.location).style("font", "12px sans-serif");
            d3.selectAll("tr." + d.name).style("background-color", "white");
            //}
        });

最佳答案

在另一种情况下,我会将我的视觉对象放入图形数据结构中并导航它以有效地更新适当的项目。但这是 d3,所以我们将做同样的事情,但我们将使用 d3 选择(它可以像图,但它们看起来更像数组),而不是我们创建的图形数据结构。从算法上讲,这种方法效率不高,但我们的图很小。

因此,向后工作我将需要一个仅包含所选节点的相邻节点的选择
节点。我将通过选择所有圆圈然后使用 d3 选择过滤器方法将其减少到仅那些相邻的圆圈来完成此操作。

当然,我需要邻居列表,但是一些不错的 js 数组方法可以使工作变得简单。最终的相关代码(在鼠标悬停中)甚至没有那么长 - 但我添加了一堆注释:

// Figure out the neighboring node id's with brute strength because the graph is small
var nodeNeighbors = graph.links.filter(function(link) {
    // Filter the list of links to only those links that have our target 
    // node as a source or target
    return link.source.index === d.index || link.target.index === d.index;})
.map(function(link) {
    // Map the list of links to a simple array of the neighboring indices - this is
    // technically not required but makes the code below simpler because we can use         
    // indexOf instead of iterating and searching ourselves.
    return link.source.index === d.index ? link.target.index : link.source.index; });

// Reset all circles - we will do this in mouseout also
svg.selectAll('circle').style('stroke', 'gray');

// now we select the neighboring circles and apply whatever style we want. 
// Note that we could also filter a selection of links in this way if we want to 
// Highlight those as well
svg.selectAll('circle').filter(function(node) {
    // I filter the selection of all circles to only those that hold a node with an
    // index in my listg of neighbors
    return nodeNeighbors.indexOf(node.index) > -1;
})
.style('stroke', 'orange');

您也可以试试 fiddle

我认为与此处相关的重要 d3 概念是,当您将数据与元素相关联时(通常在选择上使用 data() 或 datum() 方法),那么该数据会与该元素保持一致,并且任何 future 的选择都将始终使用它。

要链接其他方面,您可以以类似的方式提取这些属性并通过 d3 链接它们。例如,对于可以添加到鼠标悬停的位置矩形:
var nodeLocations = graph.links.filter(function(link) {
        return link.source.index === d.index || link.target.index === d.index;})
    .map(function(link) {
        return link.source.index === d.index ? link.target.location : link.source.location; });

d3.selectAll("rect").filter(function(node) { return nodeLocations.indexOf(node.location) > -1; }) .style("stroke", "cyan");

关于d3.js - 将多个鼠标悬停事件应用于相邻(连接)节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16857806/

相关文章:

css - 如何在 CSS 中为 SVG 元素添加边框/轮廓/描边?

javascript - 如何显示 c3.js 没有数据但有空列的图例?

javascript - 从链接设置为悬停状态的 JVectormap

javascript - Sound Manager 2 基本示例重定向问题(mp3 在单独页面上)

search - 如何让 Vim 取消突出显示您搜索的内容?

jquery - 如何使用 "highlight"jquery 效果而不暂时隐藏背景图像?

css - 如何禁用文本选择突出显示

javascript - 如何将 D3 树布局的方向改变 90 度

javascript - jQuery 在 mouseenter 上添加类并在 mouseout 后 500 毫秒删除它

javascript - d3 节点内的 Angular 指令