【问题标题】:In d3 force directed, how do I change a nodes shape by clicking on it?在 d3 forcedirected 中,如何通过单击更改节点形状?
【发布时间】:2016-11-11 02:51:56
【问题描述】:

我在 d3 中有一个力有向图,并且希望能够单击圆形节点并将它们变成矩形。然后,如果我单击一个矩形,我希望它恢复为圆形。

我查看了this 和有关 SO 的相关问题,但我认为它们适用于 D3 的早期版本,不适用于我。

我可以做到这一点,这样我的圆圈的大小和颜色会在点击时发生变化,并且使用以下代码我可以将圆圈节点替换为黑色矩形,但是它没有附加到图形上,只是一个黑色svg 上的正方形。

node.on("click", function(d,i) {

      var size = 20;
      d3.select(this).remove();

      svg.append("rect")
          .attr("x", d.x)
          .attr("y", d.y)
          .attr("height", size)
          .attr("width", size)
          .style("fill", function(d) {
            return color( d.group);
          });
})

谁能告诉我我错过了什么?我怀疑rect 没有附加到图形数据,但我对 d3 不够熟悉,无法理解我应该改变什么。谢谢你。

【问题讨论】:

    标签: javascript node.js d3.js svg graph


    【解决方案1】:

    当你说:

    我已经查看了关于 SO 的 this 和相关问题,但我认为它们适用于 D3 的早期版本,不适用于我。

    在我看来,that answer 中的任何内容都表明它不适用于 D3 v4.x。值得一提的是,在您链接的答案(和问题)中,node 是一个组元素,因此this 指的是组,而不是圆/矩形。

    继续,一个可能的解决方案(不涉及删除和附加元素)是模拟一个带有矩形的圆:

    node.append("rect")
        .attr("width", 16)
        .attr("height", 16)
        .attr("rx", 8)
        .attr("ry", 8)
    

    并且,在点击函数内部,改变rxry

    function click() {
        if(d3.select(this).attr("rx") == 8){
            d3.select(this).attr("rx", 0).attr("ry", 0);
        } else {
            d3.select(this).attr("rx", 8).attr("ry", 8);};
    };
    

    这是一个演示:

    var nodes = [
      {"id": 1},
      {"id": 2},
      {"id": 3},
      {"id": 4},
      {"id": 5},
      {"id": 6},
      {"id": 7},
      {"id": 8},
      {"id": 9},
      {"id": 10},
      {"id": 11},
      {"id": 12}
    ];
    
    var links = [
      {source: 1, target: 8},
      {source: 1, target: 3},
      {source: 1, target: 4},
    	{source: 1, target: 9},
    	{source: 1, target: 10},
    	{source: 1, target: 11},
      {source: 2, target: 5},
      {source: 2, target: 6},
    	{source: 2, target: 7},
    	{source: 2, target: 12},
      {source: 2, target: 4},
    	{source: 2, target: 8},
      {source: 6, target: 7},
      {source: 6, target: 8},
      {source: 6, target: 9},
    	{source: 6, target: 5},
      {source: 6, target: 3},
      {source: 6, target: 9},
    ]
    
    var index = 10;
    var svg = d3.select("svg"),
        width = +svg.attr("width"),
        height = +svg.attr("height"),
        node,
        link;
    
    var simulation = d3.forceSimulation()
        .force("link", d3.forceLink().id(function(d) { return d.id; }))
        .force("charge", d3.forceManyBody())
    		.force("collide", d3.forceCollide(30))
        .force("center", d3.forceCenter(width / 2, height / 2));
    
    update();
    function update() {
      link = svg.selectAll(".link")
        .data(links, function(d) { return d.target.id; })
    
      link = link.enter()
        .append("line")
        .attr("class", "link");
    
      node = svg.selectAll(".node")
        .data(nodes, function(d) { return d.id; })
    
      node = node.enter()
        .append("g")
        .attr("class", "node");
    
      node.append("rect")
    		.attr("width", 16)
        .attr("height", 16)
    		.attr("rx", 8)
    		.attr("ry", 8)
    		.attr("fill", "teal")
    		.on("click", click);
    
      simulation
          .nodes(nodes)
          .on("tick", ticked);
    
      simulation.force("link")
          .links(links);
    }
    
    
    function click() {
      if(d3.select(this).attr("rx") == 8){d3.select(this).attr("rx", 0).attr("ry", 0);}
    	else{d3.select(this).attr("rx", 8).attr("ry", 8);};
    }
    
    function ticked() {
      link
          .attr("x1", function(d) { return d.source.x + 8; })
          .attr("y1", function(d) { return d.source.y + 8; })
          .attr("x2", function(d) { return d.target.x+ 8; })
          .attr("y2", function(d) { return d.target.y+ 8; });
    
      node
          .attr("transform", function(d) { return "translate(" + d.x + ", " + d.y + ")"; });
    }
    .link {
      stroke: #aaa;
    }
    
    .node {
      stroke: none;
      stroke-width: 40px;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="400" height="300"></svg>

    【讨论】:

    • 谢谢。查看您的答案,我发现我没有注意到我正在谈论的另一个 SO 答案中对 ticked() 代码的更改,这可能是它对我不起作用的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    相关资源
    最近更新 更多