如何使鼠标悬停功能永久

时间:2017-12-04 11:25:41

标签: d3.js

我想在节点和链接上的文本上创建一个永久可见文本的力图。

snippet在节点上提供标签。

答案为Show tool-tip on links of force directed graph in d3js的第二个片段在链接和节点上提供鼠标悬停标签。

我正在尝试扩展第二个以使鼠标悬停节点标签永久化。

var width = 400;
var height = 125;
var margin = 20;
var pad = margin / 2;

var graph = {  "nodes":[ { "name": "A"}, { "name": "B"}] };
drawGraph(graph);

function drawGraph(graph) {
  var svg = d3.select("#force").append("svg")
    .attr("width", width)
    .attr("height", height);

  // create an area within svg for plotting graph
  var plot = svg.append("g")
    .attr("id", "plot")
    .attr("transform", "translate(" + pad + ", " + pad + ")");

  var layout = d3.layout.force()
    .size([width - margin, height - margin])
    .charge(-120)
    .nodes(graph.nodes)
    .start();

  drawNodes(graph.nodes);

  // add ability to drag and update layout
  d3.selectAll(".node").call(layout.drag);

  layout.on("tick", function() {
    d3.selectAll(".node")
      .attr("cx", d =>  { return d.x; })
      .attr("cy", d =>  { return d.y; });
      
  });
}

// Draws nodes on plot
function drawNodes(nodes) {

  d3.select("#plot").selectAll(".node")
    .data(nodes)
    .enter()
    .append("circle")
    .attr("class", "node")
    .attr("id", (d, i) => { return d.name;  })
    .attr("cx", (d, i) => { return d.x;  })
    .attr("cy", (d, i) => { return d.y;  })
    .attr("r",  4)
    .style("fill", "#EE77b4")
    .on("mouseover", function(d, i) {

      var x = d3.mouse(this)[0];
      var y = d3.mouse(this)[1];
      var tooltip = d3.select("#plot")
        .append("text")
        .text(d.name)
        .attr("x", x)
        .attr("y", y)
        .attr("id", "tooltip");

    })
    .on("mouseout", function(d, i) {
      d3.select("#tooltip").remove();
    });
}
body {
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 300;
}
b {
  font-weight: 900;
}
.outline {
  fill: none;
  stroke: #888888;
  stroke-width: 1px;
}
#tooltip {
  font-size: 10pt;
  font-weight: 900;
  fill: #000000;
  stroke: #ffffff;
  stroke-width: 0.25px;
}
.node {
  stroke: #ffffff;
  stroke-weight: 1px;
}
.highlight {
  stroke: red;
  stroke-weight: 4px;
  stroke-opacity: 1.0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div align="center" id="force"></div>

我尝试用:

替换鼠标悬停功能
.each( function(d, i) {
      var x = d.x; //d3.mouse(this)[0];
      var y = d.y; //d3.mouse(this)[1];
      var tooltip = d3.select("#plot")
        .append("text")
        .text(d.name)
        .attr("x", x)
    .attr("y", y)
    .attr("id", "tooltip");

    })

但是现在标签没有移动所以我添加了

d3.selectAll("text").attr( "x", d => { return d.x; })
                    .attr( "y", d => { return d.y; });
layout.on("tick", function() ...

中的

但现在一切都在一个地方不动,我得到TypeError: d is undefined

1 个答案:

答案 0 :(得分:2)

以这种方式重写代码(注意评论):

  layout.on("tick", function() {
    tooltips // here we set new position for tooltips on every tick
      .attr("x", (d, i) => { return d.x;  })
      .attr("y", (d, i) => { return d.y;  });

    d3.selectAll(".node")
      .attr("cx", d =>  { return d.x; })
      .attr("cy", d =>  { return d.y; });

  });

...

function drawNodes(nodes) {
  tooltips = d3.select("#plot").selectAll(".node")
    .data(nodes)
    .enter()
    .append("circle")
    .attr("class", "node")
    .attr("id", (d, i) => { return d.name;  })
    .attr("cx", (d, i) => { return d.x;  })
    .attr("cy", (d, i) => { return d.y;  })
    .attr("r",  4)
    .style("fill", "#EE77b4")
    .select(function() { return this.parentNode }) // returns to parent node
    .append('text') // append svg-text elements for tooltip
    .data(nodes)
    .text(function(d) { return d.name; }) // set text
    .attr("x", (d, i) => { return d.x;  }) // set initial x position
    .attr("y", (d, i) => { return d.y;  }) // set initial y position
    .attr("id", function(d,i) { return "tooltip-" + i; }) // set unique id
    .attr("class", "d3-tooltip");
}

工作演示:

var width = 400;
var height = 125;
var margin = 20;
var pad = margin / 2;
var tooltips = null;

var graph = {  "nodes":[ { "name": "A"}, { "name": "B"}] };
drawGraph(graph);

function drawGraph(graph) {
  var svg = d3.select("#force").append("svg")
    .attr("width", width)
    .attr("height", height);

  // create an area within svg for plotting graph
  var plot = svg.append("g")
    .attr("id", "plot")
    .attr("transform", "translate(" + pad + ", " + pad + ")");

  var layout = d3.layout.force()
    .size([width - margin, height - margin])
    .charge(-120)
    .nodes(graph.nodes)
    .start();

  drawNodes(graph.nodes);

  // add ability to drag and update layout
  d3.selectAll(".node").call(layout.drag);

  layout.on("tick", function() {
    tooltips
      .attr("x", (d, i) => { return d.x;  })
      .attr("y", (d, i) => { return d.y;  });
    
    d3.selectAll(".node")
      .attr("cx", d =>  { return d.x; })
      .attr("cy", d =>  { return d.y; });
      
  });
}

// Draws nodes on plot
function drawNodes(nodes) {
  tooltips = d3.select("#plot").selectAll(".node")
    .data(nodes)
    .enter()
    .append("circle")
    .attr("class", "node")
    .attr("id", (d, i) => { return d.name;  })
    .attr("cx", (d, i) => { return d.x;  })
    .attr("cy", (d, i) => { return d.y;  })
    .attr("r",  4)
    .style("fill", "#EE77b4")
    .select(function() { return this.parentNode })
    .append('text')
    .data(nodes)
    .text(function(d) { return d.name; })
    .attr("x", (d, i) => { return d.x;  })
    .attr("y", (d, i) => { return d.y;  })
    .attr("class", "d3-tooltip")
    .attr("id", function(d,i) { return "tooltip-" + i; });
}
body {
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 300;
}
b {
  font-weight: 900;
}
.outline {
  fill: none;
  stroke: #888888;
  stroke-width: 1px;
}
.d3-tooltip {
  font-size: 20pt;
  font-family: 'Comic Sans MS';
  font-weight: 900;
  fill: #000000;
  stroke: #ffffff;
  stroke-width: 0.25px;
}
.node {
  stroke: #ffffff;
  stroke-weight: 1px;
}
.highlight {
  stroke: red;
  stroke-weight: 4px;
  stroke-opacity: 1.0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div align="center" id="force"></div>