简体   繁体   English

带滑块的 D3 图形也需要更改外部节点的颜色

[英]D3 graph with slider need too change color of outside nodes

I have a D3 script that creates a graph that has a slider on the side.我有一个 D3 脚本,它创建一个侧面有一个滑块的图形。 This slider will only display link nodes that have a degree indicated by the slider.此滑块将仅显示具有滑块指示的度数的链接节点。 All other nodes will be disconnected and off to the side.所有其他节点将断开连接并移到一边。

Currently, this code displays all nodes the same color.目前,此代码以相同的颜色显示所有节点。 I would like the ability to make the nodes on the outside a different color (ie gray) to distinguish better from the ones that are connected.我希望能够使外部的节点具有不同的颜色(即灰色),以便更好地与连接的节点区分开来。

I imagine it shouldn't be too difficult.我想应该不会太难。 In the brushed function it checks the threshold to the nodes degrees and removes the links.在刷过的函数中,它检查节点度的阈值并删除链接。 maybe if degree < threshold, color = gray.也许如果度 < 阈值,颜色 = 灰色。 or check the link?或检查链接? I can't see to make it work.我看不到让它工作。

If ( "no links" )
      node.append("circle")
      .attr("r", 5)
      .style("fill", "gray")

Any assistance would be welcome!欢迎任何帮助!

My script below我的脚本如下

<!DOCTYPE html>
<meta charset="utf-8">
<title>Slider Graph 2</title>
<style>

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

.link {
  stroke: #999;
  stroke-opacity: .6;
}

.axis {
  opacity: 0.5;
  font: 10px sans-serif;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}

.axis .domain {
  fill: none;
  stroke: #000;
  stroke-opacity: .3;
  stroke-width: 4px;
  stroke-linecap: round;
}

.axis .halo {
  fill: none;
  stroke: #ddd;
  stroke-width: 3px;
  stroke-linecap: round;
}

text {
  pointer-events: none;
  font: 10px sans-serif;
  stroke: none;
  fill: gray;

}


.slider .handle {
  fill: #fff;
  stroke: #000;
  stroke-opacity: .5;
  stroke-width: 1.25px;
  cursor: grab;
}

</style>
<body>
  <script src="https://d3js.org/d3.v3.min.js"></script>
  <script>

    var width = 1000,
    height = 700;

    var color = d3.scale.category20();

    var force = d3.layout.force()
    .charge(-150)
    .linkDistance(60)
    .size([width, height]);

// gets largest degree for slider
d3.json("test4.json", function(error, graph) {
  if (error) throw error;
  var g = 0

  graph.nodes.forEach(function(d,i){
    if (d.degree > g){
      g = d.degree;

    }

  });
  console.log(g); 
  var x = d3.scale.linear()
  .domain([0, g+2])
  .range([250, 80])
  .clamp(true);



  var brush = d3.svg.brush()
  .y(x)
  .extent([0, 0]);

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

  var links_g = svg.append("g");

  var nodes_g = svg.append("g");

  svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(" + (width - 20)  + ",0)")
  .call(d3.svg.axis()
    .scale(x)
    .orient("left")
    .tickFormat(function(d) { return d; })
    .tickSize(0)
    .tickPadding(12))
  .select(".domain")
  .select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
  .attr("class", "halo");

  var slider = svg.append("g")
  .attr("class", "slider")
  .call(brush);

  slider.selectAll(".extent,.resize")
  .remove();

  var handle = slider.append("circle")
  .attr("class", "handle")
  .attr("transform", "translate(" + (width - 20) + ",0)")
  .attr("r", 5);

  svg.append("text")
  .attr("x", width - 15)
  .attr("y", 60)
  .attr("text-anchor", "end")
  .attr("font-size", "12px")
  .style("opacity", 0.5)
  .text("degree threshold")


//Get file
d3.json("test4.json", function(error, graph) {
  if (error) throw error;
  

  graph.links.forEach(function(d,i){ d.i = i; });
  graph.nodes.forEach(function(d,i){ d.i = i; });

  function brushed() {
    var value = brush.extent()[0];

    if (d3.event.sourceEvent) {
      value = x.invert(d3.mouse(this)[1]);
      brush.extent([value, value]);
    }
    handle.attr("cy", x(value));
    var threshold = value;
    console.log(graph.nodes);
    var thresholded_nodes = graph.nodes.filter(function(d){ return (d.degree > threshold);});
    var thresholded_links = graph.links.filter(function(d){ return (d.min_degree > threshold);});
    console.log(thresholded_nodes);

 //     node.append("circle")
  //    .attr("r", 5)
  //    .style("fill", "red")
  //  force
  //  .links(thresholded_links);

    var link = links_g.selectAll(".link")
    .data(thresholded_links, function(d){ return d.i; });

    link.enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function(d) { return Math.sqrt(d.value); });

    link.exit().remove();


    force.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("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });

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

    force.start();

  }

  force
  .nodes(graph.nodes);


  var node = nodes_g.selectAll(".node")
  .data(graph.nodes)
  .enter()
  .append('g')
  .attr("class", "node")
  .call(force.drag);
  
  node.append("circle")
  .attr("r", 5)
  // .style("fill", function(d) { return color(1); })
  .style("fill", function(d) {
    return color(1);
  })
  
  node.append("text")
  .attr("dy", ".35em")
  .text(function(d) { return d.name });

  node.append("title")
  .text(function(d) {
    return d.name;
  });


  // var node = nodes_g.selectAll(".node")
  // .data(graph.nodes)
  // .enter().append("circle")
  // .attr("class", "node")
  // .attr("r", 5)
  //     // .style("fill", function(d) { return color(1); })
  //     .style("fill", function(d) { return color(1); })
  //     .call(force.drag);
      // node.append("title")
      // .attr("dx", function(d){return -20})
      // .text(function(d) { return d.name; });

      brush.on("brush", brushed);

      slider
      .call(brush.extent([5, 5]))
      .call(brush.event);

    });
});

</script>

Link to test data 测试数据链接

EDIT: It should be checking the link's Min degree, and if that is less than the threshold, both nodes in the link should be gray.编辑:它应该检查链接的最小度数,如果小于阈值,链接中的两个节点都应该是灰色的。

This is D3 v3.这是 D3 v3。 In that version, there is a property named weight , which indicates if a node has links:在那个版本中,有一个名为weight的属性,它指示一个节点是否有链接:

According to the API :根据API

weight - the node weight; weight - 节点权重; the number of associated links.关联链接的数量。

So, you just need:所以,你只需要:

node.each(function(d) {
    d3.select(this).select("circle")
    .style("fill", d.weight ? color(1) : "#ccc")
  })

Here is your code with that change:这是带有该更改的代码:

 var jobject = `{"nodes":[ {"name":"ADH1A","degree":9}, {"name":"ADH1B","degree":10}, {"name":"ADH1C","degree":9}, {"name":"ADH4","degree":10}, {"name":"ADH5","degree":9}, {"name":"ADH7","degree":9}, {"name":"ALDH1A1","degree":11}, {"name":"ALDH2","degree":9}, {"name":"BDNF","degree":5}, {"name":"CHRNA5","degree":1}, {"name":"CHRNB4","degree":2}, {"name":"CNR1","degree":1}, {"name":"COMT","degree":13}, {"name":"CRHR1","degree":1}, {"name":"CYP2E1","degree":9}, {"name":"DRD1","degree":7}, {"name":"DRD2","degree":9}, {"name":"DRD3","degree":4}, {"name":"DRD4","degree":6}, {"name":"GABRA1","degree":9}, {"name":"GABRA2","degree":8}, {"name":"GABRA6","degree":7}, {"name":"GABRB1","degree":8}, {"name":"GABRB2","degree":8}, {"name":"GABRB3","degree":7}, {"name":"GABRG1","degree":5}, {"name":"GABRG2","degree":8}, {"name":"GAL","degree":5}, {"name":"GRIK3","degree":1}, {"name":"GRIN2B","degree":3}, {"name":"GRM8","degree":4}, {"name":"HTR1A","degree":2}, {"name":"HTR1B","degree":5}, {"name":"HTR2A","degree":5}, {"name":"MAOA","degree":17}, {"name":"NPY","degree":7}, {"name":"OPRD1","degree":4}, {"name":"OPRK1","degree":6}, {"name":"OPRM1","degree":3}, {"name":"PDYN","degree":6}, {"name":"POMC","degree":10}, {"name":"SLC6A3","degree":8}, {"name":"SLC6A4","degree":13}, {"name":"TPH1","degree":3} ], "links":[ {"source":0,"target":1,"min_degree":9}, {"source":0,"target":2,"min_degree":9}, {"source":0,"target":3,"min_degree":9}, {"source":0,"target":4,"min_degree":9}, {"source":0,"target":5,"min_degree":9}, {"source":0,"target":6,"min_degree":9}, {"source":0,"target":7,"min_degree":9}, {"source":0,"target":8,"min_degree":9}, {"source":0,"target":11,"min_degree":9}, {"source":1,"target":2,"min_degree":9}, {"source":1,"target":3,"min_degree":10}, {"source":1,"target":4,"min_degree":9}, {"source":1,"target":5,"min_degree":9}, {"source":1,"target":6,"min_degree":10}, {"source":1,"target":7,"min_degree":10}, {"source":1,"target":8,"min_degree":9}, {"source":1,"target":9,"min_degree":9}, {"source":1,"target":11,"min_degree":10}, {"source":2,"target":3,"min_degree":9}, {"source":2,"target":4,"min_degree":9}, {"source":2,"target":5,"min_degree":9}, {"source":2,"target":6,"min_degree":9}, {"source":2,"target":8,"min_degree":9}, {"source":2,"target":9,"min_degree":9}, {"source":2,"target":11,"min_degree":9}, {"source":3,"target":4,"min_degree":9}, {"source":3,"target":5,"min_degree":9}, {"source":3,"target":6,"min_degree":10}, {"source":3,"target":7,"min_degree":10}, {"source":3,"target":8,"min_degree":9}, {"source":3,"target":9,"min_degree":9}, {"source":3,"target":11,"min_degree":10}, {"source":4,"target":5,"min_degree":9}, {"source":4,"target":6,"min_degree":9}, {"source":4,"target":8,"min_degree":9}, {"source":4,"target":9,"min_degree":9}, {"source":4,"target":11,"min_degree":9}, {"source":5,"target":6,"min_degree":9}, {"source":5,"target":8,"min_degree":9}, {"source":5,"target":9,"min_degree":9}, {"source":5,"target":11,"min_degree":9}, {"source":6,"target":8,"min_degree":9}, {"source":6,"target":9,"min_degree":9}, {"source":6,"target":10,"min_degree":9}, {"source":6,"target":11,"min_degree":11}, {"source":6,"target":24,"min_degree":10}, {"source":7,"target":8,"min_degree":9}, {"source":7,"target":9,"min_degree":9}, {"source":7,"target":11,"min_degree":13}, {"source":7,"target":13,"min_degree":7}, {"source":7,"target":18,"min_degree":2}, {"source":7,"target":21,"min_degree":2}, {"source":7,"target":23,"min_degree":7}, {"source":7,"target":25,"min_degree":8}, {"source":7,"target":39,"min_degree":6}, {"source":7,"target":41,"min_degree":6}, {"source":8,"target":9,"min_degree":9}, {"source":9,"target":11,"min_degree":9}, {"source":10,"target":12,"min_degree":5}, {"source":10,"target":15,"min_degree":6}, {"source":10,"target":22,"min_degree":5}, {"source":10,"target":23,"min_degree":7}, {"source":10,"target":24,"min_degree":9}, {"source":10,"target":25,"min_degree":8}, {"source":10,"target":39,"min_degree":6}, {"source":10,"target":41,"min_degree":6}, {"source":11,"target":13,"min_degree":7}, {"source":11,"target":20,"min_degree":5}, {"source":11,"target":23,"min_degree":7}, {"source":11,"target":25,"min_degree":8}, {"source":11,"target":34,"min_degree":13}, {"source":11,"target":37,"min_degree":5}, {"source":11,"target":39,"min_degree":6}, {"source":11,"target":41,"min_degree":6}, {"source":12,"target":13,"min_degree":5}, {"source":12,"target":14,"min_degree":4}, {"source":12,"target":15,"min_degree":5}, {"source":12,"target":16,"min_degree":4}, {"source":13,"target":22,"min_degree":5}, {"source":13,"target":23,"min_degree":7}, {"source":13,"target":24,"min_degree":7}, {"source":13,"target":25,"min_degree":7}, {"source":14,"target":22,"min_degree":4}, {"source":14,"target":23,"min_degree":4}, {"source":14,"target":24,"min_degree":4}, {"source":15,"target":22,"min_degree":5}, {"source":15,"target":23,"min_degree":6}, {"source":15,"target":24,"min_degree":6}, {"source":15,"target":26,"min_degree":6}, {"source":16,"target":22,"min_degree":4}, {"source":16,"target":23,"min_degree":4}, {"source":16,"target":24,"min_degree":4}, {"source":17,"target":18,"min_degree":1}, {"source":19,"target":20,"min_degree":1}, {"source":20,"target":25,"min_degree":5}, {"source":20,"target":34,"min_degree":5}, {"source":20,"target":43,"min_degree":3}, {"source":21,"target":37,"min_degree":2}, {"source":24,"target":38,"min_degree":4}, {"source":24,"target":39,"min_degree":6}, {"source":24,"target":40,"min_degree":3}, {"source":24,"target":42,"min_degree":1}, {"source":25,"target":34,"min_degree":8}, {"source":25,"target":36,"min_degree":3}, {"source":25,"target":37,"min_degree":5}, {"source":26,"target":27,"min_degree":8}, {"source":26,"target":28,"min_degree":7}, {"source":26,"target":29,"min_degree":8}, {"source":26,"target":30,"min_degree":8}, {"source":26,"target":31,"min_degree":7}, {"source":26,"target":32,"min_degree":5}, {"source":26,"target":33,"min_degree":8}, {"source":26,"target":34,"min_degree":9}, {"source":27,"target":28,"min_degree":7}, {"source":27,"target":29,"min_degree":8}, {"source":27,"target":30,"min_degree":8}, {"source":27,"target":31,"min_degree":7}, {"source":27,"target":32,"min_degree":5}, {"source":27,"target":33,"min_degree":8}, {"source":27,"target":34,"min_degree":8}, {"source":28,"target":29,"min_degree":7}, {"source":28,"target":30,"min_degree":7}, {"source":28,"target":31,"min_degree":7}, {"source":28,"target":33,"min_degree":7}, {"source":28,"target":34,"min_degree":7}, {"source":29,"target":30,"min_degree":8}, {"source":29,"target":31,"min_degree":7}, {"source":29,"target":32,"min_degree":5}, {"source":29,"target":33,"min_degree":8}, {"source":29,"target":34,"min_degree":8}, {"source":30,"target":31,"min_degree":7}, {"source":30,"target":32,"min_degree":5}, {"source":30,"target":33,"min_degree":8}, {"source":30,"target":34,"min_degree":8}, {"source":31,"target":33,"min_degree":7}, {"source":31,"target":34,"min_degree":7}, {"source":32,"target":33,"min_degree":5}, {"source":33,"target":34,"min_degree":8}, {"source":34,"target":36,"min_degree":3}, {"source":34,"target":37,"min_degree":5}, {"source":34,"target":43,"min_degree":3}, {"source":35,"target":36,"min_degree":1}, {"source":37,"target":43,"min_degree":3}, {"source":38,"target":39,"min_degree":4}, {"source":38,"target":40,"min_degree":3}, {"source":38,"target":41,"min_degree":4}, {"source":39,"target":41,"min_degree":6}, {"source":40,"target":41,"min_degree":3} ]}` var graph = JSON.parse(jobject); var width = 960, height = 500; var color = d3.scale.category20(); var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var x = d3.scale.linear() .domain([0, 20]) .range([250, 80]) .clamp(true); var brush = d3.svg.brush() .y(x) .extent([0, 0]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var links_g = svg.append("g"); var nodes_g = svg.append("g"); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(" + (width - 20) + ",0)") .call(d3.svg.axis() .scale(x) .orient("left") .tickFormat(function(d) { return d; }) .tickSize(0) .tickPadding(12)) .select(".domain") .select(function() { return this.parentNode.appendChild(this.cloneNode(true)); }) .attr("class", "halo"); var slider = svg.append("g") .attr("class", "slider") .call(brush); slider.selectAll(".extent,.resize") .remove(); var handle = slider.append("circle") .attr("class", "handle") .attr("transform", "translate(" + (width - 20) + ",0)") .attr("r", 5); svg.append("text") .attr("x", width - 15) .attr("y", 60) .attr("text-anchor", "end") .attr("font-size", "12px") .style("opacity", 0.5) .text("degree threshold") graph.links.forEach(function(d, i) { di = i; }); graph.nodes.forEach(function(d, i) { di = i; }); function brushed() { var value = brush.extent()[0]; if (d3.event.sourceEvent) { value = x.invert(d3.mouse(this)[1]); brush.extent([value, value]); } handle.attr("cy", x(value)); var threshold = value; var thresholded_nodes = graph.nodes.filter(function(d) { return (d.degree > threshold); }); var thresholded_links = graph.links.filter(function(d) { return (d.min_degree > threshold); }); force .links(thresholded_links); var link = links_g.selectAll(".link") .data(thresholded_links, function(d) { return di; }); link.enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); link.exit().remove(); force.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(" + dx + "," + dy + ")"; }); }); force.start(); node.each(function(d) { d3.select(this).select("circle").style("fill", d.weight ? color(1) : "#ccc") }) } force .nodes(graph.nodes); var node = nodes_g.selectAll(".node") .data(graph.nodes) .enter() .append('g') .attr("class", "node") .call(force.drag); node.append("circle") .attr("r", 5) // .style("fill", function(d) { return color(1); }) .style("fill", function(d) { return color(1); }) node.append("text") .attr("dx", 4) .attr("dy", ".35em") .text(function(d) { return d.name }); node.append("title") .text(function(d) { return d.name; }); brush.on("brush", brushed); slider .call(brush.extent([5, 5])) .call(brush.event);
 .node { stroke: #fff; stroke-width: 1.5px; } .link { stroke: #999; stroke-opacity: .6; } .axis { opacity: 0.5; font: 10px sans-serif; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .axis .domain { fill: none; stroke: #000; stroke-opacity: .3; stroke-width: 4px; stroke-linecap: round; } .axis .halo { fill: none; stroke: #ddd; stroke-width: 3px; stroke-linecap: round; } text { pointer-events: none; font: 8px sans-serif; stroke: none; fill: red; } .slider .handle { fill: #fff; stroke: #000; stroke-opacity: .5; stroke-width: 1.25px; cursor: grab; }
 <script src="https://d3js.org/d3.v3.min.js"></script>

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

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