如何在D3中选择svg中的元素

时间:2013-11-24 01:55:54

标签: javascript svg d3.js

我在D3中有一个应用程序,形成一个类似网络的结构,它有几个相互连接的节点。现在我想选择该网络的一部分,并且还想要所选部分的值。我在我发布了我的屏幕截图this is the network i created using D3

i want this type of selection

现在我想选择富士康和亚马逊节点,也想要他们的价值..

这是我在D3中的代码..

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}

#licensing {
fill: green;
} 

.link.licensing {
stroke: green;
}

.link.resolved {
stroke-dasharray: 0, 2 1;
}

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

text {
font: 10px sans-serif;
pointer-events: none;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="app.css">
<script>
    // http://blog.thomsonreuters.com/index.php/mobile-patent-suits-graphic-of-the-day/

    /*Here licensing type is making the green arrow
     *Here resolved type is making the solid arrow
     *Here suit type is making the dotted arrow
     *
     *
     **/

    var links = [ {
        source : "Microsoft",
        target : "Amazon",
        type : "licensing"
    }, {
        source : "Microsoft",
        target : "HTC",
        type : "licensing"
    }, {
        source : "Samsung",
        target : "Apple",
        type : "suit"
    }, {
        source : "Motorola",
        target : "Apple",
        type : "suit"
    }, {
        source : "Nokia",
        target : "Apple",
        type : "resolved"
    }, {
        source : "HTC",
        target : "Apple",
        type : "suit"
    }, {
        source : "Kodak",
        target : "Apple",
        type : "suit"
    }, {
        source : "Kodak",
        target : "Qualcomm",
        type : "licensing"
    } ];

    var nodes = {};

    // Compute the distinct nodes from the links.
    links.forEach(function(link) {
        link.source = nodes[link.source] || (nodes[link.source] = {
            name : link.source
        });
        link.target = nodes[link.target] || (nodes[link.target] = {
            name : link.target
        });
    });

    var width = 960, height = 500;

    var force = d3.layout.force().nodes(d3.values(nodes)).links(links)
            .size([ width, height ]).linkDistance(60).charge(-300).on(
                    "tick", tick).start();

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

    var gStates = svg.selectAll("g.state").data(links);

    var drag = d3.behavior.drag().on("drag", function(d, i) {
        var selection = d3.selectAll('.selected');

        if (selection[0].indexOf(this) == -1) {
            selection.classed("selected", false);
            selection = d3.select(this);
            selection.classed("selected", true);
        }

        selection.attr("transform", function(d, i) {
            d.x += d3.event.dx;
            d.y += d3.event.dy;
            return "translate(" + [ d.x, d.y ] + ")"
        })
        // reappend dragged element as last
        // so that its stays on top
        this.parentNode.appendChild(this);
        d3.event.sourceEvent.stopPropagation();
    });


    // Per-type markers, as they don't inherit styles.
    svg.append("defs").selectAll("marker").data(
            [ "suit", "licensing", "resolved" ]).enter().append("marker")
            .attr("id", function(d) {
                return d;
            }).attr("viewBox", "0 -5 10 10").attr("refX", 15).attr("refY",
                    -1.5).attr("markerWidth", 6).attr("markerHeight", 6)
            .attr("orient", "auto").append("path").attr("d",
                    "M0,-5L10,0L0,5");

    var path = svg.append("g").selectAll("path").data(force.links())
            .enter().append("path").attr("class", function(d) {
                return "link " + d.type;
            }).attr("marker-end", function(d) {
                return "url(#" + d.type + ")";
            });

    var circle = svg.append("g").selectAll("circle").data(force.nodes())
            .enter().append("circle").attr("r", 6).call(force.drag);

    var text = svg.append("g").selectAll("text").data(force.nodes())
            .enter().append("text").attr("x", 8).attr("y", ".31em").text(
                    function(d) {
                        return d.name;
                    });

    // Use elliptical arc path segments to doubly-encode directionality.
    function tick() {
        path.attr("d", linkArc);
        circle.attr("transform", transform);
        text.attr("transform", transform);
    }

    function linkArc(d) {
        var dx = d.target.x - d.source.x, dy = d.target.y - d.source.y, dr = Math
                .sqrt(dx * dx + dy * dy);
        return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr
                + " 0 0,1 " + d.target.x + "," + d.target.y;
    }

    function transform(d) {
        return "translate(" + d.x + "," + d.y + ")";
    }
</script>

2 个答案:

答案 0 :(得分:4)

您可以使用.filter()过滤选择。在你的情况下,这看起来像这样。

var selected = circle.filter(function(d) {
         return d.name == "Amazon" || d.name == "Foxconn";
});

现在,您可以对该选择进行操作,其中this将是circle元素,并且数据可以通常的方式访问。

selected.each(function(d) {
  // d contains the data for the node and this is the circle element
});

答案 1 :(得分:1)

当你使用enter()追加节点时,我认为你应该添加一些属性来标记

节点,例如id

<!doctype html>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <title>Template Index</title>
</head>
<body>

  <ul id="comp">
  </ul>

    <script src="http://d3js.org/d3.v3.min.js"></script>
  <script>
  var company = [
    { id: "IBM", value: "222"},
    { id: "MS", value: "222"},
    { id: "Google", value: "222"}
  ];
  var comp = d3.select("#comp").selectAll(".com")
    .data(company)
    .enter()
    .append("li")
    .attr("id", function (d) { return "id" + d.id; })
    .text(function (d) { return d.id; });

  var ibm = d3.select("#idIBM").datum();
  console.log(ibm); // Object { id="IBM", value="222"}
  </script>
</body>
</html>

然后你可以得到选择投掷d3

然后通过datum()

获取选择中绑定的对象数据

更新:我更新文件并在firefox chrome和ie10中测试它运行良好