javascript - D3 强制布局悬停在箭头上

标签 javascript jquery html css d3.js

我正在构建一个有向图,在 hover 事件中我想突出显示相关节点、链接和邻居。一切顺利,直到我向链接添加箭头。

我不知道如何突出显示箭头和链接。

欢迎任何帮助。

jsfiddle:https://jsfiddle.net/dkroaefw/3/

代码:

graph = {
  "nodes": [{
    "name": "a"
  }, {
    "name": "b"
  }, {
    "name": "c"
  }, {
    "name": "d"
  }, {
    "name": "e"
  }, {
    "name": "f"
  }, {
    "name": "g"
  }],
  "links": [{
    "source": 0,
    "target": 1,
    "value" :1
  }, {
    "source": 1,
    "target": 2,
    "value" :1
  }, {
    "source": 1,
    "target": 3,
    "value" :1
  }, {
    "source": 0,
    "target": 4,
    "value" :1
  }, {
    "source": 4,
    "target": 5,
    "value" :1
  }, {
    "source": 4,
    "target": 6,
    "value" :1
  }]
}

var linkedByIndex = {};
graph.links.forEach(function(d) {
  linkedByIndex[d.source + "," + d.target] = true;
});

function isConnected(a, b) {
  return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index;
}

function hasConnections(a) {
  for (var property in linkedByIndex) {
    s = property.split(",");
    if ((s[0] == a.index || s[1] == a.index) && linkedByIndex[property])
      return true;
  }
  return false;
}

var width = 500
  height = 400

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

// Zoom definition
var zoom = d3.behavior.zoom()
  .scaleExtent([1, 10])
  .on("zoom", zoomed);

function zoomed() {
  container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

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


var rect = svg.append("rect")
  .attr("width", width)
  .attr("height", height)
  .style("fill", "none")
  .style("pointer-events", "all")
  .call(zoom);

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

// build the arrow.
var arrow = container.append("svg:defs")
  .selectAll("marker")
  .data(["end"]) // Different link/path types can be defined here
  .enter().append("svg:marker") // This section adds in the arrows
  .attr("class", "arrow")
  .attr("id", String)
  .attr("viewBox", "0 -5 10 10")
  .attr("refX", 20)
  .attr("markerWidth", 6)
  .attr("markerHeight", 6)
  .attr("orient", "auto")
  .append("svg:path")
  .attr("d", "M0,-5L10,0L0,5");

var link = container.append("g")
  .attr("class", "links")
  .selectAll(".links")
  .data(force.links())
  .enter().append("line")
  .attr("class", "link")
  .attr("marker-end", "url(#end)");

var node = container.append("g")
  .attr("class", "nodes")
  .selectAll(".node")
  .data(force.nodes())
  .enter().append("g")
  .attr("class", "node")
  .attr("cx", function(d) {
    return d.x;
  })
  .attr("cy", function(d) {
    return d.y;
  })
  .on("mouseover", mouseover)
  .on("mouseout", mouseout)
  .call(force.drag);

node.append("circle")
  .attr("r", 5);

node.append("text")
  .attr("class", "text")
  .attr("x", 12)
  .attr("dy", ".35em")
  .text('')

force.on("tick", function(f) {

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

function mouseover(d) {
  d3.select(this).select("circle").transition()
    .duration(750)
    .attr("r", 8);
  set_highlight(d);
}

function mouseout(d) {
  d3.select(this).select("circle").transition()
    .duration(750)
    .attr("r", 5);
  exit_highlight(d)
}

function set_highlight(d) {
  node.select("text").text(function(o) {
    return isConnected(d, o) ? o.name : "";
  })
  node.attr("class", function(o) {
    return isConnected(d, o) ? "node-active" : "node";
  });
  link.attr("class", function(o) {
    return o.source.index == d.index || o.target.index == d.index ? "link-active" : "link";
  });
}

function exit_highlight(d) {
  node.attr("class", "node");
  link.attr("class", "link");
  node.select("text").text("")
}

最佳答案

恕我直言,您需要考虑两件事:

  1. 由于您只想突出显示某些箭头,因此您需要定义两个标记并切换链接的标记。
  2. 您还需要自行切换链接的样式。

所以基本上 - 查看 this fiddle查看完整的更改:

  var arrows = defs
     .selectAll("marker")
     // let's add two markers: one for unhovered links and one for hovered links.
     .data(["end", "end-active"]) // Different link/path types can be defined here
     .enter().append("svg:marker") // This section adds in the arrows
     .attr("id", String)
     .attr("viewBox", "0 -5 10 10")
     .attr("refX", 20)
     .attr("markerWidth", 6)
     .attr("markerHeight", 6)
     .attr("orient", "auto")
     .append("svg:path")
     .attr("d", "M0,-5L10,0L0,5");

     //define the classes for each of the markers.
     defs.select("#end").attr("class", "arrow");
     defs.select("#end-active").attr("class", "arrow-active");
//...
// then further down in function set_highlight and exit highlight:
function set_highlight(d) {
  node.select("text").text(function(o) {
    return isConnected(d, o) ? o.name : "";
  })
  node.attr("class", function(o) {
    return isConnected(d, o) ? "node-active" : "node";
  });
  link.attr("marker-end", function(o) {
    return o.source.index == d.index || o.target.index == d.index ? "url(#end-active)" : "url(#end)";
  });
  link.attr("class", function(o) {
    return o.source.index == d.index || o.target.index == d.index ? "link-active" : "link";
  });
}



function exit_highlight(d) {
  node.attr("class", "node");
  link.attr("class", "link");
  link.attr("marker-end", "url(#end)");
  node.select("text").text("")
}

编辑:如果您想重用一些代码,您可以添加:

// inside the set_highlight function
    link.attr("marker-end", function(o) {
        return isLinkForNode(d, o) ? "url(#end-active)" : "url(#end)";
    });
    link.attr("class", function(o) {
        return isLinkForNode(d, o) ? "link-active" : "link";
    });


function isLinkForNode(node, link) {
    return link.source.index == node.index || link.target.index == node.index;
}

关于javascript - D3 强制布局悬停在箭头上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36185522/

相关文章:

javascript - Meteor 在运行时更改数据库

Javascript:跟踪自定义事件

javascript - 仅在移动设备而非桌面上显示 slider

javascript - 函数完成后获取事件

javascript - 如何限制对 jQuery 变量值的更改?

html - 如何使用 Bootstrap 更改部分导航栏的背景颜色

javascript - FileReader - 支持哪些编码?

javascript - 如何使用 AJAX 读取直播数据

javascript - JavaScript 中的模态弹出窗口不起作用

javascript - 使用 jQuery 对 DOM 节点进行排序 - 当前代码交替反转