在d3 js双树中单独翻转链接 [英] Flipping the links alone in a d3 js doubletree

查看:122
本文介绍了在d3 js双树中单独翻转链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我按照本教程制作双树并将弯头连接器转换为对角线连接器。
这是我尝试的



到目前为止,应该向左边的边也向正确的方向,我怎么能翻转那些边缘到左边。



我试着替换 nodes.forEach 函数,如下所示。在第二种情况下,链接被翻转,但节点从右到左。

  nodes.forEach {
if(d.isRight)
{
dy = d.depth * 180 + halfWidth;
}
else
{
dy = width - (d.depth * 180 + halfWidth);
}

});

无法使用。任何帮助是赞赏。



  var margin = {top:30,right:10,bottom:10,left:10},width = 960 -  margin.left  -  margin.right,halfWidth = width / 2,height = 500  -  margin.top  -  margin.bottom,i = 0,duration = 500,root; var getChildren = function(d){var a = ; if(d.winners)for(var i = 0; i  

  .node circle {cursor:pointer; fill:#fff;中风:钢蓝stroke-width:1.5px;}。node text {font:10px sans-serif;} path.link {fill:none; stroke:#ccc; stroke-width:1.5px;}  

 < script src =https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js>< / script>< div id =chart>< / div>  

解决方案



  var margin = {top:30,right:10,bottom:10,left:10},width = 960  -  margin.left  -  margin.right,halfWidth = width / 2,height = 500  -  margin.top  -  margin.bottom ,i = 0,duration = 500,root; var getChildren = function(d){var a = []; if(d.winners)for(var i = 0; i  

  .node circle {cursor:pointer; fill:#fff;中风:钢蓝stroke-width:1.5px;}。node text {font:10px sans-serif;} path.link {fill:none; stroke:#ccc; stroke-width:1.5px;}  

 < script src =https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js>< / script>< div id =chart>< / div>  


I'm following this tutorial to make a double tree and convert the elbow connectors into diagonal connectors. Here is what I tried

As of now the edges that are supposed to go to the left are also going in the right direction , how can i flip those edges to the left.

I tried replacing the nodes.forEach function as follows. In the second case the links got flipped , but the nodes went from right to left.

nodes.forEach(function(d) {
    if(d.isRight)
    {
       d.y = d.depth * 180 + halfWidth;
    }
    else
    {
       d.y = width - (d.depth * 180 + halfWidth);
    }

  });

Did not work. Any help is appreciated.

var margin = {
    top: 30,
    right: 10,
    bottom: 10,
    left: 10
  },
  width = 960 - margin.left - margin.right,
  halfWidth = width / 2,
  height = 500 - margin.top - margin.bottom,
  i = 0,
  duration = 500,
  root;

var getChildren = function(d) {
  var a = [];
  if (d.winners)
    for (var i = 0; i < d.winners.length; i++) {
      d.winners[i].isRight = false;
      d.winners[i].parent = d;
      a.push(d.winners[i]);
    }
  if (d.challengers)
    for (var i = 0; i < d.challengers.length; i++) {
      d.challengers[i].isRight = true;
      d.challengers[i].parent = d;
      a.push(d.challengers[i]);
    }
  return a.length ? a : null;
};

var tree = d3.layout.tree()
  .size([height, width]);

var diagonal = d3.svg.diagonal()
  .projection(function(d) {
    return [d.y, d.x];
  });

var connector = diagonal;

var calcLeft = function(d) {
  var l = d.y;
  if (!d.isRight) {
    l = d.y - halfWidth;
    l = halfWidth - l;
  }
  return {
    x: d.x,
    y: l
  };
};

var vis = d3.select("#chart").append("svg")
  .attr("width", width + margin.right + margin.left)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

setTimeout(function() {
  var json = {
    "name": "Overall Winner",
    "winners": [{
      "name": "Winner Left 1",
      "winners": [{
        "name": "Winner Left 3"
      }, {
        "name": "Winner Left 4"
      }]
    }, {
      "name": "Winner Left 2"
    }],
    "challengers": [{
      "name": "Challenger Right 1",
      "challengers": [{
        "name": "Challenger Right 3"
      }, {
        "name": "Challenger Right 4"
      }]
    }, {
      "name": "Challenger Right 2",
      "challengers": [{
        "name": "Challenger Right 5"
      }, {
        "name": "Challenger Right 6"
      }]
    }]
  };

  root = json;
  root.x0 = height / 2;
  root.y0 = width / 2;

  var t1 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
      return d.winners;
    }),
    t2 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
      return d.challengers;
    });
  t1.nodes(root);
  t2.nodes(root);

  var rebuildChildren = function(node) {
    node.children = getChildren(node);
    if (node.children) node.children.forEach(rebuildChildren);
  }
  rebuildChildren(root);
  root.isRight = false;
  update(root);
});

var toArray = function(item, arr, d) {
  arr = arr || [];
  var dr = d || 1;
  var i = 0,
    l = item.children ? item.children.length : 0;
  arr.push(item);
  if (item.position && item.position === 'left') {
    dr = -1;
  }
  item.y = dr * item.y;
  for (; i < l; i++) {
    toArray(item.children[i], arr, dr);
  }
  return arr;
};

function update(source) {
  // Compute the new tree layout.
  var nodes = toArray(source);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) {
    d.y = d.depth * 180 + halfWidth;
  });

  // Update the nodes…
  var node = vis.selectAll("g.node")
    .data(nodes, function(d) {
      return d.id || (d.id = ++i);
    });

  // Enter any new nodes at the parent's previous position.
  var nodeEnter = node.enter().append("g")
    .attr("class", "node")
    .attr("transform", function(d) {
      return "translate(" + source.y0 + "," + source.x0 + ")";
    })
    .on("click", click);

  nodeEnter.append("circle")
    .attr("r", 1e-6)
    .style("fill", function(d) {
      return d._children ? "lightsteelblue" : "#fff";
    });

  nodeEnter.append("text")
    .attr("dy", function(d) {
      return d.isRight ? 14 : -8;
    })
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.name;
    })
    .style("fill-opacity", 1e-6);

  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
    .duration(duration)
    .attr("transform", function(d) {
      p = calcLeft(d);
      return "translate(" + p.y + "," + p.x + ")";
    });

  nodeUpdate.select("circle")
    .attr("r", 4.5)
    .style("fill", function(d) {
      return d._children ? "lightsteelblue" : "#fff";
    });

  nodeUpdate.select("text")
    .style("fill-opacity", 1);

  // Transition exiting nodes to the parent's new position.
  var nodeExit = node.exit().transition()
    .duration(duration)
    .attr("transform", function(d) {
      p = calcLeft(d.parent || source);
      return "translate(" + p.y + "," + p.x + ")";
    })
    .remove();

  nodeExit.select("circle")
    .attr("r", 1e-6);

  nodeExit.select("text")
    .style("fill-opacity", 1e-6);

  // Update the links...
  var link = vis.selectAll("path.link")
    .data(tree.links(nodes), function(d) {
      return d.target.id;
    });

  // Enter any new links at the parent's previous position.
  link.enter().insert("path", "g")
    .attr("class", "link")
    .attr("d", function(d) {
      var o = {
        x: source.x0,
        y: source.y0
      };
      return connector({
        source: o,
        target: o
      });
    });

  // Transition links to their new position.
  link.transition()
    .duration(duration)
    .attr("d", connector);

  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
    .duration(duration)
    .attr("d", function(d) {
      var o = calcLeft(d.source || source);
      if (d.source.isRight) o.y -= halfWidth - (d.target.y - d.source.y);
      else o.y += halfWidth - (d.target.y - d.source.y);
      return connector({
        source: o,
        target: o
      });
    })
    .remove();

  // Stash the old positions for transition.
  nodes.forEach(function(d) {
    var p = calcLeft(d);
    d.x0 = p.x;
    d.y0 = p.y;
  });

  // Toggle children on click.
  function click(d) {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    update(source);
  }
}

.node circle {

  cursor: pointer;

  fill: #fff;

  stroke: steelblue;

  stroke-width: 1.5px;

}

.node text {

  font: 10px sans-serif;

}

path.link {

  fill: none;

  stroke: #ccc;

  stroke-width: 1.5px;

}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>

解决方案

With some efforts found a work around to do the same.

Here goes the code.

var margin = {
    top: 30,
    right: 10,
    bottom: 10,
    left: 10
  },
  width = 960 - margin.left - margin.right,
  halfWidth = width / 2,
  height = 500 - margin.top - margin.bottom,
  i = 0,
  duration = 500,
  root;

var getChildren = function(d) {
  var a = [];
  if (d.winners)
    for (var i = 0; i < d.winners.length; i++) {
      d.winners[i].isRight = false;
      d.winners[i].parent = d;
      a.push(d.winners[i]);
    }
  if (d.challengers)
    for (var i = 0; i < d.challengers.length; i++) {
      d.challengers[i].isRight = true;
      d.challengers[i].parent = d;
      a.push(d.challengers[i]);
    }
  return a.length ? a : null;
};

var tree = d3.layout.tree()
  .size([height, width]);

var diagonal = d3.svg.diagonal()
  .projection(function(d) {
    return [d.y, d.x];
  });

var connector = diagonal;

var calcLeft = function(d) {
  var l = d.y;
  if (!d.isRight) {
    l = d.y - halfWidth;
    l = halfWidth - l;
  }
  return {
    x: d.x,
    y: l
  };
};

var vis = d3.select("#chart").append("svg")
  .attr("width", width + margin.right + margin.left)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

setTimeout(function() {
  var json = {
    "name": "Overall Winner",
    "winners": [{
      "name": "Winner Left 1",
      "winners": [{
        "name": "Winner Left 3"
      }, {
        "name": "Winner Left 4"
      }]
    }, {
      "name": "Winner Left 2"
    }],
    "challengers": [{
      "name": "Challenger Right 1",
      "challengers": [{
        "name": "Challenger Right 3"
      }, {
        "name": "Challenger Right 4"
      }]
    }, {
      "name": "Challenger Right 2",
      "challengers": [{
        "name": "Challenger Right 5"
      }, {
        "name": "Challenger Right 6"
      }]
    }]
  };

  root = json;
  root.x0 = height / 2;
  root.y0 = width / 2;

  var t1 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
      return d.winners;
    }),
    t2 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
      return d.challengers;
    });
  t1.nodes(root);
  t2.nodes(root);

  var rebuildChildren = function(node) {
    node.children = getChildren(node);
    if (node.children) node.children.forEach(rebuildChildren);
  }
  rebuildChildren(root);
  root.isRight = false;
  update(root);
});

var toArray = function(item, arr, d) {
  arr = arr || [];
  var dr = d || 1;
  var i = 0,
    l = item.children ? item.children.length : 0;
  arr.push(item);
  if (item.position && item.position === 'left') {
    dr = -1;
  }
  item.y = dr * item.y;
  for (; i < l; i++) {
    toArray(item.children[i], arr, dr);
  }
  return arr;
};

function update(source) {
  // Compute the new tree layout.
  var nodes = toArray(source);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) {
    if (d.isRight) {
      d.y = d.depth * 180 + halfWidth;
    } else {
      d.y = width - (d.depth * 180 + halfWidth);
    }

  });


  // Update the nodes…
  var node = vis.selectAll("g.node")
    .data(nodes, function(d) {
      return d.id || (d.id = ++i);
    });

  // Enter any new nodes at the parent's previous position.
  var nodeEnter = node.enter().append("g")
    .attr("class", "node")
    .attr("transform", function(d) {
      return "translate(" + source.y0 + "," + source.x0 + ")";
    })
    .on("click", click);

  nodeEnter.append("circle")
    .attr("r", 1e-6)
    .style("fill", function(d) {
      return d._children ? "lightsteelblue" : "#fff";
    });

  nodeEnter.append("text")
    .attr("dy", function(d) {
      return d.isRight ? 14 : -8;
    })
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.name;
    })
    .style("fill-opacity", 1e-6);

  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
    .duration(duration)
    .attr("transform", function(d) {
      console.log(d);
      p = calcLeft(d);
      if (d.isRight) {

        return "translate(" + p.y + "," + p.x + ")";
      } else {
        if (p.y != 470) {
          var temp = p.y - 470;
          p.y = 470 - temp;
          return "translate(" + p.y + "," + p.x + ")";
        } else {
          return "translate(" + p.y + "," + p.x + ")";
        }
      }
    });

  nodeUpdate.select("circle")
    .attr("r", 4.5)
    .style("fill", function(d) {
      return d._children ? "lightsteelblue" : "#fff";
    });

  nodeUpdate.select("text")
    .style("fill-opacity", 1);

  // Transition exiting nodes to the parent's new position.
  var nodeExit = node.exit().transition()
    .duration(duration)
    .attr("transform", function(d) {
      p = calcLeft(d.parent || source);
      return "translate(" + p.y + "," + p.x + ")";
    })
    .remove();

  nodeExit.select("circle")
    .attr("r", 1e-6);

  nodeExit.select("text")
    .style("fill-opacity", 1e-6);

  // Update the links...
  var link = vis.selectAll("path.link")
    .data(tree.links(nodes), function(d) {
      return d.target.id;
    });

  // Enter any new links at the parent's previous position.
  link.enter().insert("path", "g")
    .attr("class", "link")
    .attr("d", function(d) {
      var o = {
        x: source.x0,
        y: source.y0
      };
      return connector({
        source: o,
        target: o
      });
    });

  // Transition links to their new position.
  link.transition()
    .duration(duration)
    .attr("d", connector);

  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
    .duration(duration)
    .attr("d", function(d) {
      var o = calcLeft(d.source || source);
      if (d.source.isRight) o.y -= halfWidth - (d.target.y - d.source.y);
      else o.y += halfWidth - (d.target.y - d.source.y);
      return connector({
        source: o,
        target: o
      });
    })
    .remove();

  // Stash the old positions for transition.
  nodes.forEach(function(d) {
    var p = calcLeft(d);
    d.x0 = p.x;
    d.y0 = p.y;
  });

  // Toggle children on click.
  function click(d) {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    update(source);
  }
}

.node circle {
  cursor: pointer;
  fill: #fff;
  stroke: steelblue;
  stroke-width: 1.5px;
}
.node text {
  font: 10px sans-serif;
}
path.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 1.5px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>

这篇关于在d3 js双树中单独翻转链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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