How to manipulate nodes based on dynamicaly changing text? (enter/exit/update)

会有一股神秘感。 提交于 2019-12-08 08:16:46

问题


I am using d3.js with the force layout. Now, with the help of the dynamically changing array data it is possible to highlight nodes dynamically based on the array. Also with the code below i am able to show up dynamically the names of the nodes, which are part of the array, as a text.

So, when the array has for example 3 entries, then 3 nodes are shown up and also 3 names of the nodes appear. Let's say their names are "a", "b", "c", so the text "a", "b", "c" appears on screen. Now, when i click on the new appeared text "a", then i want the node, which contains that name, to be filled green. I tried this with the function called specialfunction. The problem is, that all nodes fill green when i click on the text "a". Can someone of you guys maybe help? Thanks.

 var texts = svg.selectAll(".texts")
        .data(data);


    textsExit = texts.exit().remove();

    textsEnter = texts.enter()
        .append("text")
        .attr("class", "texts");

    textsUpdate = texts.merge(textsEnter)
        .attr("x", 10)
        .attr("y", (d, i) => i * 16)
        .text(d => d.name)
        .on("click", specialfunction);

  function specialfunction(d) { 


         node.style("fill", function(d){ return this.style.fill = 'green';});

             };

回答1:


Right now, your specialFunction function is only taking the nodes selection and setting the style of all its elements to the returned value of...

this.style.fill = 'green';

... which is, guess what, "green".

Instead of that, filter the nodes according to the clicked text:

function specialFunction(d) {
    nodes.filter(function(e) {
        return e === d
    }).style("fill", "forestgreen")
}

In this simple demo, d is the number for both texts and circles. Just change d in my demo to d.name or any other property you want. Click the text and the correspondent circle will change colour:

var svg = d3.select("svg");
var data = d3.range(5);
var nodes = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 30 + d * 45
  })
  .attr("r", 20)
  .style("fill", "lightblue")
  .attr("stroke", "gray");

var texts = svg.selectAll(null)
  .data(data)
  .enter()
  .append("text")
  .attr("y", 88)
  .attr("x", function(d) {
    return 26 + d * 45
  })
  .attr("fill", "dimgray")
  .attr("cursor", "pointer")
  .text(function(d) {
    return d
  })
  .on("click", specialFunction);

function specialFunction(d) {
  nodes.filter(function(e) {
    return e === d
  }).style("fill", "forestgreen")
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

EDIT: Answering your comment, this even simpler function can set the circles to the original colour:

function specialFunction(d) {
    nodes.style("fill", function(e){
        return e === d ? "forestgreen" : "lightblue"; 
    })
}

Here is the demo:

var svg = d3.select("svg");
var data = d3.range(5);
var nodes = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 30 + d * 45
  })
  .attr("r", 20)
  .style("fill", "lightblue")
  .attr("stroke", "gray");

var texts = svg.selectAll(null)
  .data(data)
  .enter()
  .append("text")
  .attr("y", 88)
  .attr("x", function(d) {
    return 26 + d * 45
  })
  .attr("fill", "dimgray")
  .attr("cursor", "pointer")
  .text(function(d) {
    return d
  })
  .on("click", specialFunction);

function specialFunction(d) {
  nodes.style("fill", function(e){
  return e === d ? "forestgreen" : "lightblue"; 
  })
}
<script src="https://d3js.org/d3.v4.min.js"></script>
    <svg></svg>


来源:https://stackoverflow.com/questions/44296937/how-to-manipulate-nodes-based-on-dynamicaly-changing-text-enter-exit-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!