javascript - 带 slider 的D3图需要添加标签

标签 javascript d3.js

我有一个 D3 脚本,它创建一个侧面有 slider 的图表。此 slider 将仅显示具有 slider 指示的度数的链接节点。所有其他节点将断开连接并移到一边。

我想为所有这些节点添加标签,将这些节点引到一边。我希望标签位于节点内部。我一直在尝试解决此网站上的其他类似问题,但我似乎无法将其与我当前的代码正确集成。

欢迎任何帮助!

下面是我的脚本

<!DOCTYPE html>
<meta charset="utf-8">
<title>Slider Graph</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;
}

.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 = 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")

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);

    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; });
    });

    force.start();

  }

  force
      .nodes(graph.nodes);

  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")
      .text(function(d) { return d.name; });

  brush.on("brush", brushed);

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

});

</script>

Test data here

最佳答案

我重写了你的代码。请检查。这是您需要的行为吗?

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) {
  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;

  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 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("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("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>

关于javascript - 带 slider 的D3图需要添加标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46856104/

相关文章:

javascript - 为什么 d3.json 不随请求发送 cookie?

javascript - 如何制作在 x 轴下方带有附加垂直线的条形图

javascript - 过滤和映射后如何获取用户ID

javascript - 从表单javascript传递变量值

javascript - 将 HTML 元素的 "Style"属性转换为 JSON

javascript - 模态时图形后面的 D3 提示

javascript - 从输入字段读取属性时 HTML 编码丢失

javascript - 防止动画进行时多次点击(stopPropagation & :animated)

javascript - 如何更改c3js中的工具提示内容

javascript - 以负值开头的 d3.js bar