D3在节点链接图中鼠标悬停链接,增加“接受”范围 [英] D3 mouse-over of links in node-link diagram, increase 'accepted' range

查看:140
本文介绍了D3在节点链接图中鼠标悬停链接,增加“接受”范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时我需要在节点链接图中以非常小的笔划宽度(<3px)显示边缘。这使得用户很难将鼠标悬停在它们上面。



我正在使用 .on('mouseover',()=> ; //做东西)功能。



是否有一种简单的方法可以增加触发鼠标悬停事件的半径?让我们说它应该总是假设边缘的笔画宽度至少为5px。



我正在动态着色边缘,但有没有办法设置边缘的颜色类似(见灰色面板为边缘,水平放置):

 透明(2px)
color(1px)
transparent(2px)

这样它实际上有一个尺寸为5px,但只能看到1px?



或者我是否真的需要计算我的边缘是否与我的鼠标手动重叠? (这绝对是可能的,但考虑到一些边缘弯曲,其他边缘不是,......这真的很麻烦)。

解决方案


是否有一种简单的方法可以增加触发鼠标悬停事件的半径?


否,事件处理程序被添加到元素中,如果一个narrow元素的笔触宽度为3px,则该函数仅在鼠标位于这些像素上时运行。


是否有一种方法可以将边缘的颜色设置为[...]实际上大小为5px,但只有1px可见?


可以使用路径并将彩色填充与透明笔划相结合。然而,一种更简单的方法就是复制选择,只需要相同的属性,并使顶部路径或行(通过顶部表示代码中后面的选择)透明和具有更大的笔画宽度。



在这个演示中,例如,有20px宽的透明线,它们捕获 mousemove 事件,在可见的窄线上:

  //首先绘制这些线条
var links = svg.selectAll(foo)
.data(edges)
.enter()
.append(line)
.style(stroke,#ccc )
.style(stroke-width,1);

//这些透明线条涂在上面,它们捕捉鼠标移动
var linksTransparent = svg.selectAll(foo)
.data(edges)
.enter()
.append(line)
.style(stroke,none)
.attr(pointer-events,all)
.style(stroke-width,20)
.on(mousemove,d => {
console.log(source:+ d.source.id +, target:+ d.target.id)
});

  var width = 400; var height = 200; var svg = d3.select(body)。append(svg)。attr(width,width).attr(height,height) ; var nodes = [{id:One},{id:Two},{id:Three},{id:Four}]; var edges = [ {source:0,target:1},{source:0,target:2},{source:0,target:3}]; var simulation = d3.forceSimulation( ).force(link,d3.forceLink()。distance(60))。force(charge,d3.forceManyBody()。strength(-200))。force(center,d3.forceCenter(width / 2,height / 2)); var links = svg.selectAll(foo)。data(edges).enter()。append(line)。style(stroke,#ccc)。style (stroke-width,1); var links2 = svg.selectAll(foo)。data(edges).enter()。append(line)。style(stroke,none)。attr (指针事件 ,all)。style(stroke-width,20).on(mousemove,d => {console.log(source:+ d.source.id +,target:+ d.target.id)}); var color = d3.scaleOrdinal(d3.schemeCategory20); var node = svg.selectAll( foo)。data(nodes).enter()。append(g)。call(d3.drag()。on(start,dragstarted).on(drag,dragged).on( end,dragended)); var nodeCircle = node.append(circle)。attr(r,10).attr(stroke,grey)。attr(fill,(d,i) => color(i)); var texts = node.append(text)。style(fill,black)。attr(dx,20).attr(dy,8)。 text(function(d){return d.id;}); simulation.nodes(nodes); simulation.force(link)。linkss(edges); simulation.on(tick,function(){links。 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;}); links2.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,(d)=>translate(+ dx +,+ dy +))});函数dragstarted(d){if(!d3.event.active)simulation .alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y;}函数被拖动(d){d.fx = d3.event.x; d.fy = d3.event.y;} function dragended(d){if(!d3.event.active)simulation.alphaTarget(0); d.fx = null; d.fy = null;}  

 < script src = https://d3js.org/d3.v4.min.js >< /脚本>  


Sometimes I need to display edges in node-link diagrams with a very small stroke-width (< 3px). This makes it very hard for the user to hover over them.

I'm using the .on('mouseover', () => //do stuff) function.

Is there an easy way to increase the radius that would trigger the mouseover event? Let's say it should always assume the edge has a stroke-width of at least 5px.

I'm coloring the edges dynamically, but is there maybe a way to set the color of the edge to something like (see the gray panel as the edge, layed out horizontally):

transparent (2px)
color (1px)
transparent (2px)

So that it actually has a size of 5px, but only 1px is visible?

Or do I really have to calculate whether or not my edge is overlapping with my mouse manually? (It's definitely possible, but given the fact that some edges are curved, others not, ... it really is a hassle).

解决方案

Is there an easy way to increase the radius that would trigger the mouseover event?

No, the event handler is added to the element, and if a narrow element has a stroke width of 3px the function will only run when the mouse is over those pixels.

Is there maybe a way to set the color of the edge to something like [...] it actually has a size of 5px, but only 1px is visible?

That's possible using a path and combining a coloured fill with a transparent stroke. However, a way easier approach is just duplicating the selection, with exactly the same attributes, and making the top paths or lines (by "top" I mean the selection that comes later in the code) transparent and with a larger stroke-width.

In this demo, for instance, there are 20px-wide transparent lines, which capture the mousemove event, over the visible narrow lines:

//these lines are painted first
var links = svg.selectAll("foo")
    .data(edges)
    .enter()
    .append("line")
    .style("stroke", "#ccc")
    .style("stroke-width", 1);

//these transparent lines are painted on top, and they capture the mousemove
var linksTransparent = svg.selectAll("foo")
    .data(edges)
    .enter()
    .append("line")
    .style("stroke", "none")
    .attr("pointer-events", "all")
    .style("stroke-width", 20)
    .on("mousemove", d => {
        console.log("source: " + d.source.id + ", target: " + d.target.id)
    });

var width = 400;
var height = 200;

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

var nodes = [{
  "id": "One"
}, {
  "id": "Two"
}, {
  "id": "Three"
}, {
  "id": "Four"
}];

var edges = [{
  "source": 0,
  "target": 1
}, {
  "source": 0,
  "target": 2
}, {
  "source": 0,
  "target": 3
}];

var simulation = d3.forceSimulation()
  .force("link", d3.forceLink().distance(60))
  .force("charge", d3.forceManyBody().strength(-200))
  .force("center", d3.forceCenter(width / 2, height / 2));

var links = svg.selectAll("foo")
  .data(edges)
  .enter()
  .append("line")
  .style("stroke", "#ccc")
  .style("stroke-width", 1);

var links2 = svg.selectAll("foo")
  .data(edges)
  .enter()
  .append("line")
  .style("stroke", "none")
  .attr("pointer-events", "all")
  .style("stroke-width", 20)
  .on("mousemove", d => {
    console.log("source: " + d.source.id + ", target: " + d.target.id)
  });

var color = d3.scaleOrdinal(d3.schemeCategory20);

var node = svg.selectAll("foo")
  .data(nodes)
  .enter()
  .append("g")
  .call(d3.drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended));

var nodeCircle = node.append("circle")
  .attr("r", 10)
  .attr("stroke", "gray")
  .attr("fill", (d, i) => color(i));

var texts = node.append("text")
  .style("fill", "black")
  .attr("dx", 20)
  .attr("dy", 8)
  .text(function(d) {
    return d.id;
  });

simulation.nodes(nodes);
simulation.force("link")
  .links(edges);

simulation.on("tick", function() {
  links.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;
    });

  links2.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", (d) => "translate(" + d.x + "," + d.y + ")")

});

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

<script src="https://d3js.org/d3.v4.min.js"></script>

这篇关于D3在节点链接图中鼠标悬停链接,增加“接受”范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆