如何仅在树形链接的一侧添加文本

时间:2020-10-22 16:53:28

标签: javascript d3.js

我正在使用d3.js绘制一棵树,当我在链接中添加方向和阈值时,它是在两侧绘制的。

我添加这样的文本:

.text(function(d) {
    return d.source.thresholds + ' ' + d.source.directions;
})

如何为该.text添加限制,以使其仅在链接的左侧而不是在两者的左侧绘制。如何设置限制,使其仅显示在左侧链接中。

例如<= 12应该仅在A的左侧链接上绘制,而不是在两个链接上绘制。

var treeData = [{
  "name": "A",
  "directions": "<=",
  "thresholds": "12",
  "children": [{
      "name": "B",
      "directions": "<=",
      "thresholds": "12",
      "children": [{
          "name": "C",
          "directions": "<=",
          "thresholds": "4",
          "children": [{
              "name": "false"
            },
            {
              "name": "true"
            }
          ]
        },
        {
          "name": "A",
          "directions": "<=",
          "thresholds": "12",
          "children": [{
              "name": "B",
              "directions": "<=",
              "thresholds": "2",
              "children": [{
                  "name": "true"
                },
                {
                  "name": "false"
                }
              ]
            },
            {
              "name": "C",
              "directions": "<=",
              "thresholds": "5",
              "children": [{
                  "name": "false"
                },
                {
                  "name": "true"
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "name": "B",
      "directions": "<=",
      "thresholds": "15",
      "children": [{
          "name": "D",
          "directions": "<=",
          "thresholds": "18",
          "children": [{
              "name": "E",
              "directions": "<=",
              "thresholds": "2.5",
              "children": [{
                  "name": "true"
                },
                {
                  "name": "false"
                }
              ]
            },
            {
              "name": "F",
              "directions": "<=",
              "thresholds": "4.8",
              "children": [{
                  "name": "false"
                },
                {
                  "name": "true"
                }
              ]
            }
          ]
        },
        {
          "name": "true"
        }
      ]
    }
  ]
}];


// ************** Generate the tree diagram  *****************
var margin = {
    top: 20,
    right: 120,
    bottom: 20,
    left: 120
  },
  width = 960 - margin.right - margin.left,
  height = 600 - margin.top - margin.bottom;

var i = 0;

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

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

var svg = d3.select("body").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 + ")");

root = treeData[0];

update(root);

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
    links = tree.links(nodes);

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

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

  // Enter the nodes.
  var nodeEnter = node.enter().append("g")
    .attr("class", "node")
    .attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")";
    });

  nodeEnter.append("circle")
    .attr("r", 10)
    .style("fill", "#fff");

  nodeEnter.append("text")
    .attr("x", function(d) {
      return d.children || d._children ? -13 : 13;
    })
    .attr("dy", ".35em")
    .attr("text-anchor", function(d) {
      return d.children || d._children ? "end" : "start";
    })
    .text(function(d) {
      return d.name;
    })
    .style("fill-opacity", 1);

  // Declare the links…
  var link = svg.selectAll("path.link")
    .data(links, function(d) {
      return d.target.id;
    });

  // Enter the links.
  link.enter().insert("path", "g")
    .attr("class", "link")
    .attr("d", diagonal);

  // Add threshold and directions
  link.enter().insert("text")
    .attr("font-family", "Arial, Helvetica, sans-serif")
    .attr("fill", "Black")
    .style("font", "normal 12px Arial")
    .attr("transform", function(d) {
      return "translate(" +
        ((d.source.x + d.target.x) / 2) + "," +
        ((d.source.y + d.target.y) / 2) + ")";
    })
    .attr("dy", ".35em")
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.source.thresholds + ' ' + d.source.directions;
    })

}
.node circle {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 3px;
}

.node text {
  font: 12px sans-serif;
}

.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

任何帮助我解决该问题的方法,将不胜感激。

1 个答案:

答案 0 :(得分:1)

您可以使用.filter()将选择减少到仅左侧节点。具体来说,要仅选择左侧具有链接的节点,可以使用

.filter(function(d) {
  return d.target.x < d.source.x;
})

在一棵树中,您有nodeslinks。节点定义了一个打印的圆圈,包括其位置(xy坐标,从左上角开始计数)。链接包含对两个node对象(其源和目标)的引用。通过说d.target.x < d.source.x,我实际上是说,我只想查看目标节点的x值比源节点低(因此更靠近左侧)的链接。

var treeData = [{
  "name": "A",
  "directions": "<=",
  "thresholds": "12",
  "children": [{
      "name": "B",
      "directions": "<=",
      "thresholds": "12",
      "children": [{
          "name": "C",
          "directions": "<=",
          "thresholds": "4",
          "children": [{
              "name": "false"
            },
            {
              "name": "true"
            }
          ]
        },
        {
          "name": "A",
          "directions": "<=",
          "thresholds": "12",
          "children": [{
              "name": "B",
              "directions": "<=",
              "thresholds": "2",
              "children": [{
                  "name": "true"
                },
                {
                  "name": "false"
                }
              ]
            },
            {
              "name": "C",
              "directions": "<=",
              "thresholds": "5",
              "children": [{
                  "name": "false"
                },
                {
                  "name": "true"
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "name": "B",
      "directions": "<=",
      "thresholds": "15",
      "children": [{
          "name": "D",
          "directions": "<=",
          "thresholds": "18",
          "children": [{
              "name": "E",
              "directions": "<=",
              "thresholds": "2.5",
              "children": [{
                  "name": "true"
                },
                {
                  "name": "false"
                }
              ]
            },
            {
              "name": "F",
              "directions": "<=",
              "thresholds": "4.8",
              "children": [{
                  "name": "false"
                },
                {
                  "name": "true"
                }
              ]
            }
          ]
        },
        {
          "name": "true"
        }
      ]
    }
  ]
}];


// ************** Generate the tree diagram  *****************
var margin = {
    top: 20,
    right: 120,
    bottom: 20,
    left: 120
  },
  width = 960 - margin.right - margin.left,
  height = 600 - margin.top - margin.bottom;

var i = 0;

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

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

var svg = d3.select("body").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 + ")");

root = treeData[0];

update(root);

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
    links = tree.links(nodes);

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

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

  // Enter the nodes.
  var nodeEnter = node.enter().append("g")
    .attr("class", "node")
    .attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")";
    });

  nodeEnter.append("circle")
    .attr("r", 10)
    .style("fill", "#fff");

  nodeEnter.append("text")
    .attr("x", function(d) {
      return d.children || d._children ? -13 : 13;
    })
    .attr("dy", ".35em")
    .attr("text-anchor", function(d) {
      return d.children || d._children ? "end" : "start";
    })
    .text(function(d) {
      return d.name;
    })
    .style("fill-opacity", 1);

  // Declare the links…
  var link = svg.selectAll("path.link")
    .data(links, function(d) {
      return d.target.id;
    });

  // Enter the links.
  link.enter().insert("path", "g")
    .attr("class", "link")
    .attr("d", diagonal);

  // Add threshold and directions
  link.enter()
    .insert("text")
    .filter(function(d) {
      return d.target.x < d.source.x;
    })
    .attr("font-family", "Arial, Helvetica, sans-serif")
    .attr("fill", "Black")
    .style("font", "normal 12px Arial")
    .attr("transform", function(d) {
      return "translate(" +
        ((d.source.x + d.target.x) / 2) + "," +
        ((d.source.y + d.target.y) / 2) + ")";
    })
    .attr("dy", ".35em")
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.source.thresholds + ' ' + d.source.directions;
    })

}
.node circle {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 3px;
}

.node text {
  font: 12px sans-serif;
}

.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>