如何在d3js中突出显示所选节点?

时间:2016-12-12 10:04:14

标签: javascript d3.js

我想在点击d3js中的任何节点时突出显示所选节点及其连接的节点, 其他节点将消失或变钝。

m[i,]

有没有办法在d3js中应用这种功能?

1 个答案:

答案 0 :(得分:3)

有几种方法可以实现。这是其中之一:

circle.on("click", function(d) {
    var thisNode = d.id
    var connected = data.links.filter(function(e) {
        return e.source === thisNode || e.target === thisNode
    });
    circle.attr("opacity", function(d) {
        return (connected.map(d => d.source).indexOf(d.id) > -1 || connected.map(d => d.target).indexOf(d.id) > -1) ? 1 : 0.1
    });

    path.attr("opacity", function(d) {
        return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.1
    });

使用您的代码检查演示:



    var color = d3.scale.category20();
    //try{
    //    var data = JSON.parse(text);
    //} catch (e) {
    //    window.alert("sometext: "+e);
    //}

    var data = {
        "nodes": [{
            "id": 127230,
            "name": "Optimization of query evaluation algorithms",
            "citation": 26,
            "group": 10
        }, {
            "id": 127254,
            "name": "Flow algorithms for parallel query optimization",
            "citation": 22,
            "group": 10
        }, {
            "id": 127380,
            "name": "Randomized approximation algorithms for query optimization problems on two processors",
            "citation": 14,
            "group": 10
        }, {
            "id": 127438,
            "name": "Optimization algorithms for simultaneous multidimensional queries in OLAP environments",
            "citation": 12,
            "group": 10
        }, {
            "id": 127063,
            "name": "Query optimization in database systems",
            "citation": 230,
            "group": 10
        }, {
            "id": 127158,
            "name": "Query optimization in a memory-resident domain relational calculus database system",
            "citation": 41,
            "group": 10
        }, {
            "id": 129760,
            "name": "An Overview of TQuel",
            "citation": 22,
            "group": 10
        }, {
            "id": 129867,
            "name": "ADVISORS",
            "citation": 10,
            "group": 10
        }, {
            "id": 129872,
            "name": "Tellabs and THRIP through the Telkom Centre of Excellence at Rhodes University.",
            "citation": 10,
            "group": 10
        }, {
            "id": 127412,
            "name": "Optimal service ordering in decentralized queries over web services",
            "citation": 13,
            "group": 10
        }, {
            "id": 130856,
            "name": "Queries over Web Services",
            "citation": 10,
            "group": 10
        }, {
            "id": 130959,
            "name": "Exploiting Parallelism to Accelerate Keyword Search On Deep-web Sources",
            "citation": 10,
            "group": 10
        }, {
            "id": 131199,
            "name": "Contents lists available at ScienceDirect Future Generation Computer Systems",
            "citation": 10,
            "group": 10
        }, {
            "id": 131211,
            "name": "Flow Algorithms for Parallel Query Optimization",
            "citation": 10,
            "group": 10
        }, {
            "id": 127373,
            "name": "Multi-query Optimization for On-Line Analytical Processing",
            "citation": 14,
            "group": 10
        }, {
            "id": 133379,
            "name": "Concise descriptions of subsets of structured sets",
            "citation": 21,
            "group": 10
        }],
        "links": [{
            "source": 127230,
            "target": 127063,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127230,
            "target": 127158,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127230,
            "target": 129760,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127230,
            "target": 129867,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127230,
            "target": 129872,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127230,
            "target": 127063,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127230,
            "target": 127158,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127230,
            "target": 129760,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127230,
            "target": 129867,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127230,
            "target": 129872,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127254,
            "target": 127412,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127254,
            "target": 130856,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127254,
            "target": 130959,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127254,
            "target": 131199,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127254,
            "target": 131211,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127254,
            "target": 127412,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127254,
            "target": 130856,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127254,
            "target": 130959,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127254,
            "target": 131199,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127254,
            "target": 131211,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127438,
            "target": 127373,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127438,
            "target": 133379,
            "name": "c1",
            "value": 10,
            "grouo": 1
        }, {
            "source": 127438,
            "target": 127373,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }, {
            "source": 127438,
            "target": 133379,
            "name": "c1",
            "value": 10,
            "grouo": 9
        }]
    };

    // used to store the number of links between two nodes. 
    // mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
    var mLinkNum = {};

    // sort links first
    // sortLinks();

    data.links.sort(function(a, b) {
        if (a.source > b.source) {
            return 1;
        } else if (a.source < b.source) {
            return -1;
        } else {
            if (a.target > b.target) {
                return 1;
            }
            if (a.target < b.target) {
                return -1;
            } else {
                return 0;
            }
        }
    })

    // set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
    setLinkIndexAndNum();


    var w = 1345,
        h = 1000;

    var force = d3.layout.force()
        .size([w, h])
        .linkDistance(100)
        .charge(-800)
        .on("tick", tick);

    var svg = d3.select("body").append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    var color = d3.scale.category10()
    var edges = [];
    data.links.forEach(function(e) {
        var sourceNode = data.nodes.filter(function(n) {
                return n.id === e.source;
            })[0],
            targetNode = data.nodes.filter(function(n) {
                return n.id === e.target;
            })[0];

        edges.push({
            source: sourceNode,
            target: targetNode,
            name: e.name,
            value: e.value,
            linkindex: e.linkindex,
            grouo: e.grouo
        });
    });

    force
        .nodes(data.nodes)
        .links(edges)
        .start();

    var path = svg.append("svg:g")
        .selectAll("line")
        .data(edges)
        .enter().append("svg:path")
        .attr("class", "link")
        .style("stroke-width", function(d, i) {
            return Math.sqrt(d.value);
        }).style('stroke', function(d) {
            return color(d.grouo);
        });


    var circle = svg.append("svg:g")
        .selectAll("circle")
        .data(force.nodes())
        .enter().append("svg:circle")
        .attr("r", function(d) {
            return (Math.sqrt(d.citation));
        })
        .style("fill", function(d) {
            return color(d.group);
        })
        .call(force.drag);

    var text = svg.append("svg:g")
        .selectAll("g")
        .data(force.nodes())
        .enter().append("svg:g");
    // A copy of the text with a thick white stroke for legibility.
    //text.append("svg:text")
    //.attr("x", 8)
    //.attr("y", ".31em")
    //.attr("class", "shadow")
    //.text(function (d) {
    //return d.name;
    //});

    text.append("svg:text")
        .attr("x", 8)
        .attr("y", ".31em")
        .text(function(d) {
            // return d.name;
        });

    circle.on("click", function(d) {
        var thisNode = d.id
        var connected = data.links.filter(function(e) {
            return e.source === thisNode || e.target === thisNode
        });
        circle.attr("opacity", function(d) {
            return (connected.map(d => d.source).indexOf(d.id) > -1 || connected.map(d => d.target).indexOf(d.id) > -1) ? 1 : 0.1
        });

        path.attr("opacity", function(d) {
            return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.1
        });

    })

    // Use elliptical arc path segments to doubly-encode directionality.
    function tick() {
        path.attr("d", function(d, i) {
            var dx = d.target.x - d.source.x,
                dy = d.target.y - d.source.y,
                dr = 30 * d.linkindex; //linknum is defined above
            var output = "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
            //console.log(d)
            return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
        });

        // Add tooltip to the connection path
        path.append("svg:title")
            .text(function(d, i) {
                return d.name;
            });

        circle.attr("transform", function(d) {
            return "translate(" + d.x + "," + d.y + ")";
        });

        text.attr("transform", function(d) {
            return "translate(" + d.x + "," + d.y + ")";
        });
    }

    // sort the links by source, then target
    function sortLinks1() {
        data.links.sort(function(a, b) {
            if (a.source > b.source) {
                return 1;
            } else if (a.source < b.source) {
                return -1;
            } else {
                if (a.target > b.target) {
                    return 1;
                }
                if (a.target < b.target) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });
    }



    //any links with duplicate source and target get an incremented 'linknum'
    function setLinkIndexAndNum1() {
        for (var i = 0; i < data.links.length; i++) {
            if (i != 0 &&
                data.links[i].source == data.links[i - 1].source &&
                data.links[i].target == data.links[i - 1].target) {
                data.links[i].linkindex = data.links[i - 1].linkindex + 1;
                console.log(data.links[i].linkindex)
            } else {
                data.links[i].linkindex = 1;
            }
            // save the total number of links between two nodes
            if (mLinkNum[data.links[i].target + "," + data.links[i].source] !== undefined) {
                mLinkNum[data.links[i].target + "," + data.links[i].source] = data.links[i].linkindex;
            } else {
                mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
            }
        }
    }

    function setLinkIndexAndNum() {

        for (var i = 0; i < data.links.length; i++) {
            if (i != 0 &&
                data.links[i].source == data.links[i - 1].source &&
                data.links[i].target == data.links[i - 1].target) {
                data.links[i].linkindex = data.links[i - 1].linkindex + 1;
            } else {
                data.links[i].linkindex = 1;
            };
        };
    }
&#13;
  path.link {
            fill: none;
            stroke: #666;
            stroke-width: 1.5px;
        }

        circle {
            fill: #ccc;
            stroke: #333;
            stroke-width: 1.5px;
        }

        text {
            font: 10px sans-serif;
            pointer-events: none;
        }

            text.shadow {
                stroke: #fff;
                stroke-width: 3px;
                stroke-opacity: .8;
            }

        body {
            background-color: white;
            margin: 0px;
        }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;