在d3js中围绕矩形形状移动svg标记

时间:2015-01-08 15:47:28

标签: svg d3.js markers

我正在使用d3使用固定的力导向布局来可视化基因网络。

该图包含矩形/椭圆形/圆形矩形节点,在这些节点之间的链接末端带有标记。到目前为止(据我所知),这些标记是通过refX和refX定位的,因此遵循连接两个节点的路径末端的径向形状。有没有什么方法可以定义“路径”或标记,使标记沿节点的形状移动而不是相对于路径末端固定距离的节点周围?

说明我的问题:

var graph = {
  "nodes": [{
    "name": "from",
    "fixed": true,
    x: 100,
    y: 100,
    w: 60,
    h: 20
  }, {
    "name": "to",
    "fixed": true,
    x: 250,
    y: 250,
    w: 60,
    h: 20
  }],
  "links": [{
    "source": 0,
    "target": 1
  }]
}
var width = 960,
  height = 500;

var force = d3.layout.force()
  .charge(-120)
  .linkDistance(300)
  .size([width, height]);

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

force.nodes(graph.nodes)
  .links(graph.links)
  .start();

var defs = svg.append("svg:defs");
var marker = defs.selectAll("marker");

marker = marker.data([{
    "type": "arrow",
    "d": "M0,-5L10,0L0,5L2,0",
    "view": "0 -5 10 10",
    "color": "#000000"
  }])
  .enter()
  .append("svg:marker")
  .attr("id", function(d) {
    return d.type;
  })
  .attr("viewBox", function(d) {
    return d.view;
  })
  .attr("refX", 30)
  .attr("refY", 0)
  .attr("markerWidth", 5)
  .attr("markerHeight", 5)
  .attr("orient", "auto");

marker.append("svg:path")
  .attr("d", function(d) {
    return d.d;
  })
  .style("fill", function(d) {
    return d.color;
  });

var link = svg.selectAll(".link")
  .data(graph.links)
  .enter().append("line")
  .attr("class", "link")
  .style("stroke-width", "5")
  .attr("marker-end", "url(#arrow)");

var node = svg.selectAll(".node")
  .data(graph.nodes)
  .enter().append("rect")
  .attr("class", "node")
  .attr("width", function(d) {
    return d.w;
  })
  .attr("height", function(d) {
    return d.h;
  })
  .style("fill", "blue")
  .call(force.drag);

node.append("title")
  .text(function(d) {
    return d.name;
  });

force.on("tick", function() {
  link.attr("x1", function(d) {
      return d.source.x + d.source.w / 2;
    })
    .attr("y1", function(d) {
      return d.source.y + d.source.h / 2;
    })
    .attr("x2", function(d) {
      return d.target.x + d.target.w / 2;
    })
    .attr("y2", function(d) {
      return d.target.y + d.target.h / 2;
    })

  node.attr("x", function(d) {
      return d.x;
    })
    .attr("y", function(d) {
      return d.y;
    });
});
.node {
  stroke: #fff;
  stroke-width: 1.5px;
}
.link {
  stroke: #999;
  stroke-opacity: .6;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

JsFiddle示例:

http://jsfiddle.net/millermaximilian/w3eq6ccc/

我非常感谢任何建议!

最高

1 个答案:

答案 0 :(得分:0)

没有内置方式。您可以根据形状的数学定义创建代码以参数化标记的位置。从根本上说,当你设置一个标记在节点是圆形时从节点以X px绘制时会发生什么,因为数学上它只是半径。虽然形状更复杂,但它更难,但当然正方形,矩形和椭圆仍然相对容易计算。对于复杂的svg:path形状,我想,您可以使用path的内置getPointAtLength的某种组合,并计算从一个节点到另一个节点的角度来做到这一点,但我不知道任何早期示例的任何实现,更不用说那样的了。