如何在d3分层边缘捆绑中突出显示源节点及其所有目标节点和对应的链接 [英] How to highlight a source node and all its target nodes and corresponding links in d3 hierarchical edge bundling

查看:86
本文介绍了如何在d3分层边缘捆绑中突出显示源节点及其所有目标节点和对应的链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是d3 JS的初学者。我已经创建了一个d3层次化边缘捆绑可视化。现在我正试图这样做:每当我将鼠标移到任何节点上(鼠标悬停事件)时,其所有目标节点和相应的链接都必须突出显示。如何执行此操作?
我当前的代码是:

I am a beginner in d3 JS. I have created a d3 hierarchical edge bundling visualization.Now i am trying to do this: whenever i move mouse over any node(mouse-over event) ,all its target nodes and the corresponding links must be highlighted.How to do this? My current code is:

<html>
    <head>

        <style>
            .node {
              font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
            .link {
              stroke: steelblue;
              stroke-opacity: .4;
              fill: none;
            }
        </style>

    </head>
    <body>
            <script src="http://d3js.org/d3.v3.min.js"></script>
            <script>
            var classes=[
{"name":"a","size":3938,"imports":["b","f"]},
{"name":"b","size":3938,"imports":[]},
{"name":"c","size":3938,"imports":["a"]},
{"name":"d","size":3938,"imports":[]},
{"name":"e","size":3938,"imports":[]},
{"name":"f","size":3938,"imports":[]}


];
                    var diameter = 960,
                        radius = diameter / 2,
                        innerRadius = radius - 120;
                    var cluster = d3.layout.cluster()
                        .size([360, innerRadius]);

                    var bundle = d3.layout.bundle();

                    var line = d3.svg.line.radial()
                        .interpolate("bundle")
                        .tension(.85)
                        .radius(function(d) { return d.y; })
                        .angle(function(d) { return d.x / 180 * Math.PI; });

                    var svg = d3.select("body").append("svg")
                        .attr("width", diameter)
                        .attr("height", diameter)
                      .append("g")
                        .attr("transform", "translate(" + radius + "," + radius + ")");



                      var nodes = cluster.nodes(packageHierarchy(classes)),
                          links = packageImports(nodes);

                      svg.selectAll(".link")
                          .data(bundle(links))
                        .enter().append("path")
                          .attr("class", "link")
                          .attr("d", line);

                      svg.selectAll(".node")
                          .data(nodes.filter(function(n) { return !n.children; }))
                        .enter().append("g")
                          .attr("class", "node")
                          .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
                        .append("text")
                          .attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
                          .attr("dy", ".31em")
                          .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
                          .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
                          .text(function(d) { return d.key; });


                    // Lazily construct the package hierarchy from class names.

                    function packageHierarchy(classes) {
                      var map = {};
                      function find(name, data) {
                        var node = map[name], i;
                        if (!node) {
                          node = map[name] = data || {name: name, children: []};
                          if (name.length) {
                            node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
                            node.parent.children.push(node);
                            node.key = name.substring(i + 1);
                          }
                        }
                        return node;
                      }
                      classes.forEach(function(d) {
                        find(d.name, d);
                      });
                      return map[""];
                    }


                    // Return a list of imports for the given array of nodes.
                    function packageImports(nodes) {
                      var map = {},
                          imports = [];
                      // Compute a map from name to node.
                      nodes.forEach(function(d) {
                        map[d.name] = d;
                      });
                      // For each import, construct a link from the source to target node.
                      nodes.forEach(function(d) {
                        if (d.imports) d.imports.forEach(function(i) {
                          imports.push({source: map[d.name], target: map[i]});
                        });
                      });
                      return imports;
                    }
                    </script>



    </body>
</html>


推荐答案

首先创建一个函数 colorNode

该函数的目标是遍历所有DOM,并使用过滤器检查数据名称是否相同。对于那些过滤的节点,使其样式填充为红色。

The goal of the function is to iterate through all the DOMs and check if the data name is same, using filter. For those filtered node make its style fill red.

            function colorNode(name){
              //iterate through all the dom and get the DOM which has the data
              var node = d3.selectAll(".node")[0].filter(function(d){
                return d3.select(d).data()[0].name == name;
              });
              //for the matching node DOM set the fill to be red
              d3.selectAll(node).style("fill", "red");
            }

与显示链接相同:

            function colorLink(src,tgt){
              //iterate through all the links for src and target.
              var link = d3.selectAll(".link")[0].filter(function(d){
                return (d3.select(d).data()[0][0].name == src && d3.select(d).data()[0][2].name == tgt);
              });
              //for the filtered link make the stroke red.
              d3.selectAll(link).style("stroke", "red");
            }

节点上的下一步配置鼠标悬停事件。

Next on the node configure mouseover event.

.on("mouseover", function(d){
                          //first make all the nodes/links black(reset).
                          d3.selectAll(".node").style("fill", "black");
                          d3.selectAll(".link").style("stroke", "steelblue");
                          //color the node which is hovered.
                          colorNode(d.name);
                          //iterate over the imports which is the targets of the node(on which it is hovered) and color them.
                          d.imports.forEach(function(name){
                            colorNode(name);
                            //color the link for a given source and target name.
                            colorLink(d.name, name);
                          });
                        })  

工作代码此处

这篇关于如何在d3分层边缘捆绑中突出显示源节点及其所有目标节点和对应的链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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