如何在强制布局d3.js中动态添加箭头标记 [英] How to append the arrow marker dynamically in force layout d3.js

查看:866
本文介绍了如何在强制布局d3.js中动态添加箭头标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在d3.js的强制布局中动态添加箭头标记,如下图所示

  d3.select('svg.svgparentTag')。selectAll(marker)。data([ BLACK,BLUE])。enter()。append(svg:marker)
.attr(id,String)
.attr(viewBox,0 -5 10 10)
.attr(markerWidth,6)
.attr(markerHeight,6)
.attr(orient,auto)
。 append(svg:path)
.attr(class,function(d){returnmarker_only+ d.type;})
.attr(d,M0, 5L10,0L0,5); // marker

var path = d3.select('。pitch')。selectAll(path)
.data(force.links())
.enter ).append('g')。classed('g_path',true).append(svg:path)。attr(class,link);


path.filter(function(d){
return d.arrow == true;
})。attr(marker-mid,function d){returnurl(#BLUE)})。attr(stroke-linecap,round);

http://bl.ocks.org/mbostock/1153292



您需要做的是创建 svg:defs 并将 svg:marker 元素放在 defs 。然后使用 marker-end marker-mid 标记之一来附加标记-start

  //每类型标记,因为它们不继承样式。 
svg.append(defs)。append(marker)
.attr(id,marker)
.attr(viewBox,0 -5 10 10)
.attr(refX,15)
.attr(refY,-1.5)
.attr(markerWidth,6)
.attr markerHeight,6)
.attr(orient,auto)
.append(path)
.attr(d,M0,-5L10,0L0 ,5);

var path = svg.append(g)。selectAll(path)
.data(force.links())
.enter path)
.attr(marker-end,url(#marker);});

如果你需要一个标记中线的直线,你可能遇到问题,如果路径中间没有节点,则绘制在中间。请查看talkol的解答,了解如何解决此 http://stackoverflow.com/a/15758791/1617269



从这个问题的接受答案改编而来,你可以有一个类似这样的生成函数,生成中间有节点的线或基于<$ c $的弧c> d.type 。查看 jsfiddle

  function tick(){
path.attr(d,function(d){
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy)/ 4,
mLx = d.source.x + dx / 2,
mLy = d.source.y + dy / 2,
mAx = d.source.x + dx,
mAy = d.source.y + dy;
if(d.type ===line){
return [
M,d.source.x,d.source.y,
L mLy,
L,d.target.x,d.target.y,
Z
] .join();
}
return [
M,d.source.x,d.source.y,
A,dr,dr,0,0,1,mAx,mAy,
A ,dr,dr,0,0,1,d.target.x,d.target.y
] .join();
});


How to append the arrow marker dynamically in force layout of d3.js as in below image

  d3.select('svg.svgparentTag').selectAll("marker").data(["BLACK", "BLUE"]).enter().append("svg:marker")
        .attr("id", String)
        .attr("viewBox", "0 -5 10 10")
        .attr("markerWidth", 6)
        .attr("markerHeight", 6)
        .attr("orient", "auto")
        .append("svg:path")
        .attr("class", function(d) { return "marker_only " + d.type; })
        .attr("d", "M0,-5L10,0L0,5"); //marker 

 var path = d3.select('.pitch').selectAll("path")
            .data(force.links())
            .enter().append('g').classed('g_path', true).append("svg:path").attr("class", "link");


 path.filter(function(d) {
            return d.arrow == true;
        }).attr("marker-mid", function(d) { return "url(#BLUE)"}).attr("stroke-linecap", "round");

解决方案

There's an example of this at http://bl.ocks.org/mbostock/1153292

What you need to do is create svg:defs and place svg:marker elements in the defs. Then attach the markers using one of the attributes marker-end, marker-mid or marker-start

// Per-type markers, as they don't inherit styles.
svg.append("defs").append("marker")
    .attr("id", "marker")
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 15)
    .attr("refY", -1.5)
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("orient", "auto")
  .append("path")
    .attr("d", "M0,-5L10,0L0,5");

var path = svg.append("g").selectAll("path")
    .data(force.links())
  .enter().append("path")
    .attr("marker-end", "url(#marker)"; });

In case you need a marker-mid for straight lines, you may run into issues with the marker not drawing in the middle if the path doesn't have a node in the middle. Have a look at the answer from talkol for how to solve this http://stackoverflow.com/a/15758791/1617269

So adapted from the accepted answer in that question, you could have a generator function like this which generates lines with a node in the middle or arcs based on d.type. Check it out on jsfiddle

function tick() {
  path.attr("d", function(d) {
    var dx = d.target.x - d.source.x,
        dy = d.target.y - d.source.y,
        dr = Math.sqrt(dx * dx + dy * dy)/4,
        mLx = d.source.x + dx/2,
        mLy = d.source.y + dy/2,
        mAx = d.source.x + dx,
        mAy = d.source.y + dy;
      if (d.type === "line") {
       return [
          "M",d.source.x,d.source.y,
           "L",mLx,mLy,
           "L",d.target.x,d.target.y,
           "Z"
          ].join(" ");
      }
    return [
      "M",d.source.x,d.source.y,
      "A",dr,dr,0,0,1,mAx,mAy,
      "A",dr,dr,0,0,1,d.target.x,d.target.y
    ].join(" ");
  });

这篇关于如何在强制布局d3.js中动态添加箭头标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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