在D3中,如何在力向图上同时支持Pan&Zoom和Mouseover?

时间:2018-08-29 17:58:43

标签: d3.js

我有一个D3力导向图。

我希望能够缩放和平移图形(使用当前代码),但也可以将鼠标悬停在元素上(不起作用,因为用于捕获缩放/平移的rect覆盖了{ {1}}应该接受circles。如何支持这两种功能?

mouseover

1 个答案:

答案 0 :(得分:0)

正如@ rioV8提到的,您要做的就是将缩放应用于SVG。非常简单。

以下是完整的代码,以防有人感兴趣:

css

.links line {
  stroke: #999;
  stroke-opacity: 0.6;
}

.nodes circle {
  stroke: #fff;
  stroke-width: 1.5px;
  cursor: pointer;
}

.tooltip {  
  position: absolute;           
  text-align: center;           
  padding: 2px; 
  font: 15px sans-serif;        
  background: lightsteelblue;   
  border: 0px;      
  border-radius: 8px;           
  pointer-events: none;         
}

javascript

const {
  nodes,
  links
} = await this.getData();

console.log(nodes)
console.log(links.map(({
  source,
  target
}) => source + '->' + target).join('\n'))

const svg = select('svg');


const width = +svg.attr("width");
const height = +svg.attr("height");

// Define the div for the tooltip
var tooltip = select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

const g = svg.append("g")
  .attr('width', width)
  .attr('height', height)


const zoomHandler = zoom()
  .scaleExtent([1 / 2, 10])
  .on("zoom", () => g.attr("transform", event.transform));

zoomHandler(svg);

const simulation = forceSimulation(nodes)
  .force("link", forceLink(links).id(d => d.id))
  .force("charge", forceManyBody())
  .force("center", forceCenter(width / 2, height / 2))
  .on("tick", ticked);

const link = g.append("g")
  .attr("stroke", "#999")
  .attr("stroke-opacity", 0.6)
  .selectAll("line")
  .data(links)
  .enter().append("line")
  .attr("stroke-width", d => d.value);

const node = g.append("g")
  .attr("stroke", "#fff")
  .attr("stroke-width", 1.5)
  .selectAll("circle")
  .data(nodes)
  .enter()
  .append("circle")
  .attr("r", 5)
  .attr("fill", (d) => d.group === 1 ? '#ff0000' : '#0000ff')
  .on("mouseover", function (d) {
    tooltip.transition()
      .duration(100)
      .style("opacity", .9);

      tooltip.html(d.id)
      .style("left", (event.pageX) + "px")
      .style("top", (event.pageY - 28) + "px");
  })
  .on("mouseout", function (d) {
    tooltip.transition()
      .duration(100)
      .style("opacity", 0);
  })
  .call(drag(simulation))

function ticked() {
  link
    .attr("x1", d => d.source.x)
    .attr("y1", d => d.source.y)
    .attr("x2", d => d.target.x)
    .attr("y2", d => d.target.y);

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