简体   繁体   English

将节点标签添加到D3网络

[英]Adding node labels to D3 Network

I can't figure out how to add node labels to my D3 force-directed network. 我无法弄清楚如何将节点标签添加到我的D3力导向网络。 This code gets the labels to show up but they won't move with the network. 此代码会显示标签,但不会随网络移动。

How can I append the text to the node itself? 如何将文本附加到节点本身? Does anybody have any suggestions? 有人有什么建议吗?

Thanks a bunch. 谢谢一堆。

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.links line {
    stroke: #999;
    stroke-opacity: .6;
    shape-rendering: geometricPrecision;
}

.nodes circle {
    stroke: #fff;
    stroke-width: 1.5px;
}

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

#tools div {
    display: inline;
}

form,
select {
    float: right;
    display: inline;
}
</style>

<body>
<div id='tools'></div>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script>
    var svg = d3.select("svg"),
        width = +svg.attr("width"),
        height = +svg.attr("height");

    var graph; //Global variable for the graph

    svg.append('rect')
        .attr('width', '100%')
        .attr('height', '100%')
        .attr('fill', '#FFFFFF');

    // Call zoom for svg container.
    svg.call(d3.zoom().on('zoom', zoomed)).on("dblclick.zoom", null);
    var container = svg.append('g');
    //Create scales for color and edge weight

    var color = d3.scaleLinear()
        .domain([1776, 2017])
        .range([0.1, 1]);

    var weight = d3.scaleLinear()
        .domain([0, 1])
        .range([1, 5]);

    // Create form for search (see function below).
    var search = d3.select("div#tools").append('form').attr('onsubmit', 'return false;');
    var box = search.append('input')
        .attr('type', 'text')
        .attr('id', 'searchTerm')
        .attr('placeholder', 'Type to search...');
    var button = search.append('input')
        .attr('type', 'button')
        .attr('value', 'Search')
        .on('click', function() {
            searchNodes();
        });

    //Toggle for ego networks on click (function below).
    var toggle = 0;

    //Create groups for nodes and links
    var link = container.append("g")
        .attr("class", "links")
        .selectAll(".link"),
        node = container.append("g")
        .attr("class", "nodes")
        .selectAll(".node");


    //Get data from json file, assign that data to graph variable.
    d3.json("semantic_great_nouns.json", function(error, json) {
        if (error) throw error;
        graph = json;
        update();
    });

    // Zooming function translates the size of the svg container.
    function zoomed() {
        container.attr("transform", "translate(" + d3.event.transform.x + ", " + d3.event.transform.y + ") scale(" + d3.event.transform.k + ")");
    }
    // Search for nodes by making all unmatched nodes temporarily transparent.
    function searchNodes() {
        var term = document.getElementById('searchTerm').value;
        var selected = container.selectAll('.node').filter(function(d, i) {
            return d.id.toString().search(term.toLowerCase()) == -1;
        });
        selected.style('opacity', '0');
        var link = container.selectAll('.link');
        link.style('stroke-opacity', '0');
        d3.selectAll('.node').transition()
            .duration(20000)
            .style('opacity', '1');
        d3.selectAll('.link').transition().duration(20000).style('stroke-opacity', '1');
    }
    //Draw the graph!
    function update() {
        //Parameters for force layout simulation
        var simulation = d3.forceSimulation(graph.nodes)
            .force("link", d3.forceLink(graph.links)) //.id(function(d) { return d.id; }))
            .force("charge", d3.forceManyBody().strength([-300])) //.distanceMax([500]))
            .force("center", d3.forceCenter(width / 2, height / 2))
            .force("x", d3.forceX())
            .force("y", d3.forceY())
            .stop();
        //The graph will be drawn behind the scenes and then displayed in static form.
        //This code tells the program how many times to iterate through the layout simulation.
        for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
            simulation.tick();
        }
        // Data join with links and corresponding nodes.
        //If we wanted to reload the graph with an adjusted node set, we could do so.
        link = link.data(graph.links, function(d) {
            return d.source.id + ', ' + d.target.id;
        });
        link.exit().remove();
        var linkEnter = link.enter().append('line')
            .attr('class', 'link');
        link = linkEnter.merge(link)
            .attr("x1", function(d) {
                return d.source.x;
            })
            .attr("y1", function(d) {
                return d.source.y;
            })
            .attr("x2", function(d) {
                return d.target.x;
            })
            .attr("y2", function(d) {
                return d.target.y;
            })
            .attr("stroke-width", function(d) {
                return weight(d.weight);
            });

        // When adding and removing graph.nodes, reassert attributes and behaviors.
        node = node.data(graph.nodes, function(d) {
            return d.id;
        });
        node.exit().remove();
        var nodeEnter = node.enter().append('circle')
            .attr('r', 20)
            .attr("fill", function(d) {
                if (d.bipartite == 1) {
                    return '#103def';
                } else {
                    return '#ed1d0e';
                }
            })
            //color bipartite nodes
            .attr('class', 'node')
            .attr('id', function(d) {
                return "n" + d.id.toString();
            })
            .attr('clickToggle', 0)
            .attr("cx", function(d) {
                return d.x;
            })
            .attr("cy", function(d) {
                return d.y;
            })
            // On click, toggle ego networks for the selected node. (See function below.)
            .on('click', function(d) {
                toggleClick(d);
            });
        node = nodeEnter.merge(node);

        //node.append("label")
        //.attr("dx", 12)
        //.attr("dy", ".35em")
        //.text(function(d) { return d.id });

        var label = svg.append("g").attr("class", "labels").selectAll("g")
            .data(graph.nodes)
            .enter().append("g");

        label.append("text")
            .attr("x", 14)
            .attr("y", ".31em")
            .style("font-family", "sans-serif")
            .style("font-size", "0.7em")
            .text(function(d) {
                return d.id;
            })
            .attr("x", function(d) {
                return d.x;
            })
            .attr("y", function(d) {
                return d.y;
            });

        // node.append("text")
        //   .attr("dx", 12)
        // .attr("dy", ".35em")
        //.text(function(d) { return d.id });

        // simulation.on("tick", function () {
        //   link.attr("x1", function (d) {return d.source.x;})
        //     .attr("y1", function (d) {return d.source.y;})
        //   .attr("x2", function (d) {return d.target.x;})
        // .attr("y2", function (d) {return d.target.y;});"""

        //node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
        // });
        //d3.selectAll("circle").attr("cx", function (d) {return d.x;})
        //  .attr("cy", function (d) {return d.y;});
        //d3.selectAll("text").attr("x", function (d) {return d.x;})
        //  .attr("y", function (d) {return d.y;});
        //});
        //node.append("title")
        //.text(function(d) { return d.id; });
    }


    // A function to handle click toggling based on neighboring nodes.
    function toggleClick(d) {
        // Make object of all neighboring nodes.
        connectedNodes = {};
        connectedNodes[d.id] = true;
        graph.links.forEach(function(l) {
            if (l.source.id == d.id) {
                connectedNodes[l.target.id] = true;
            } else if (l.target.id == d.id) {
                connectedNodes[l.source.id] = true;
            };
        });
        if (toggle == 0) {
            // Ternary operator restyles links and nodes if they are adjacent.
            d3.selectAll('.link').style('stroke-opacity', function(l) {
                return l.target == d || l.source == d ? 1 : 0.2;
            });
            d3.selectAll('.node').style('opacity', function(n) {
                if (n.id in connectedNodes) {
                    return 1;
                } else {
                    return 0.2;
                };
            });
            // Show information when node is clicked
            d3.select('div#tools').append('span').text(d.date);
            toggle = 1;
        } else {
            // Restore nodes and links to normal opacity.
            d3.selectAll('.link').style('stroke-opacity', 0.6);
            d3.selectAll('.node').style('opacity', 1);
            d3.selectAll('span').remove();
            toggle = 0;
        }
    }
</script>

Please see this link: http://codepen.io/rafszul/pen/KeAaG/ 请看这个链接: http//codepen.io/rafszul/pen/KeAaG/

it might help you. 它可能会帮助你。

try replacing "circle" by "rect" in JS, CSS section. 尝试在JS,CSS部分"circle" by "rect"替换"circle" by "rect"

also replace this snippet into JS code to specify width and height of rectangle: 也将此代码段替换为JS代码以指定矩形的宽度和高度:

var circle = svg.append("g").selectAll("rect")

    .data(force.nodes())
    .enter().append("rect")
    .attr("width", 15)
    .attr("height", 15)
    .call(force.drag);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM