d3.js Tree - 子节点的分页 v3.5 [英] d3.js Tree - Paging of child nodes v3.5

查看:25
本文介绍了d3.js Tree - 子节点的分页 v3.5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 上一个问题解决了许多子节点分页的问题

I have a previous question which solves a problem with paging of many child nodes

尽管在我的 d3.js 上下文中实现,但几乎没有问题:

There are few problems though with implementing in my d3.js context:

  • 发起分页的第一个和最后一个子节点没有命名'...' 根据脚本功能.这似乎是 v7 到 v3.5 的问题.

  • The first and last child nodes that initiate the paging are not named '...' according to the script functionality. This appears to be a v7 to v3.5 issue.

分页应该只发生在叶子节点上,而不是任何中间分支.

The paging should only occur on the leaf nodes, not any middle branches.

它需要与 d3.js v3.5 一起使用(是的,我知道,但这是待定的将树迁移到 v7...).基本上主要问题是第一个和最后一个分页节点的命名...

It needs to work with d3.js v3.5 (yes I know, but this is pending migrating the tree to v7...). Basically the main issue is with naming of the first and last paging nodes...

请参阅 fiddle 了解 d3.js v3.5 中的实现和问题

See fiddle for implementation and issues in d3.js v3.5

与之前的解决方案相关:

Relevant from previous solution:

function pageNodes(d, maxNode) {
  if (d.children) {
    d.children.forEach(c => pageNodes(c, maxNode));
    if (d.children.length > maxNode) {
      d.pages = {}
      const count = maxNode - 2;
      const l = Math.ceil(d.children.length / count);
      for (let i = 0; i < l; i++) {
        let startRange = i * count;
        let endRange = i * count + count;
        d.pages[i] = d.children.slice(startRange, endRange);
        d.pages[i].unshift({
          ...d.pages[i][0],
          data: {
            name: "..."
          },
          page: i == 0 ? l - 1 : i - 1
        })

        // console.log(i, d.pages[i]);
        d.pages[i].push({
          ...d.pages[i][0],
          data: {
            name: "..."
          },
          page: i != (l - 1) ? i + 1 : 0,
        });
      }
      d.children = d.pages[0];
      console.log(d.pages)
    }
  }
}
root.children.forEach(c => pageNodes(c, 8));

function click(d) {
if (d.hasOwnProperty('page')) {
      d.parent.children = d.parent.pages[d.page];
    }  else if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
  update(d);
}

推荐答案

注意事项

  • 顺序是强制性的 pageNodes 函数需要在调用折叠函数之前调用,因为折叠将 children 键更改为 _children>pageNodes 函数与 children 键一起使用
  • 我以某种方式创建了 pageNodes 函数,因此它不需要反复调用会浪费计算能力,所以我们在开始时调用它一次,然后根据需要调整结构,然后我们只需使用点击功能无需反复调用 pageNodes.
  • 我修改了 pageNodes 函数,只在数据包含 page: true 时才分页,参考你可以查看 unit-group 数据段.
  • Notes

    • The order is mandatory pageNodes function needs to be called before collapse function call, As collapse changes the children key to _children and pageNodes function works with children key
    • I created pageNodes function in a way so it does not require calling again and again which would waste computation power, so we call it once on start and the structure is adjusted as per requirement then we just work with click function without requiring to call pageNodes again and again.
    • I have modified the pageNodes function to only page if data contain page: true, for reference you can check unit-group data segment.
    • var treeData = {"name":"Program","column_to_sort_by":null,"type":"program","children":[{"name":"ProgramGroup1","column_to_sort_by":null,"type":"program_group","children":[{"name":"POGroup1","column_to_sort_by":null,"type":"1program_outcome_group","children":[{"name":"PO1","column_to_sort_by":null,"type":"program_outcome","children":[{"name":"Unit1","column_to_sort_by":"Unit1","children":[{"name":"UG1-LE","column_to_sort_by":null,"page":true,"type":"unit_group","children":[{"name":"LE1","column_to_sort_by":"LE1","type":"learning_event"},{"name":"LE10","column_to_sort_by":"LE10","type":"learning_event"},{"name":"LE11","column_to_sort_by":"LE11","type":"learning_event"},{"name":"LE12","column_to_sort_by":"LE12","type":"learning_event"},{"name":"LE13","column_to_sort_by":"LE13","type":"learning_event"},{"name":"LE14","column_to_sort_by":"LE14","type":"learning_event"},{"name":"LE15","column_to_sort_by":"LE15","type":"learning_event"},{"name":"LE2","column_to_sort_by":"LE2","type":"learning_event"},{"name":"LE4","column_to_sort_by":"LE4","type":"learning_event"},{"name":"LE5","column_to_sort_by":"LE5","type":"learning_event"},{"name":"LE6","column_to_sort_by":"LE6","type":"learning_event"},{"name":"LE7","column_to_sort_by":"LE7","type":"learning_event"},{"name":"LE8","column_to_sort_by":"LE8","type":"learning_event"},{"name":"LE9","column_to_sort_by":"LE9","type":"learning_event"}]},{"name":"UG1-Assessments","column_to_sort_by":null,"page":true,"type":"unit_group","children":[{"name":"ASST1","column_to_sort_by":"ASST1","type":"assessment"},{"name":"ASST10","column_to_sort_by":"ASST10","type":"assessment"},{"name":"ASST11","column_to_sort_by":"ASST11","type":"assessment"},{"name":"ASST13","column_to_sort_by":"ASST13","type":"assessment"},{"name":"ASST14","column_to_sort_by":"ASST14","type":"assessment"},{"name":"ASST15","column_to_sort_by":"ASST15","type":"assessment"},{"name":"ASST2","column_to_sort_by":"ASST2","type":"assessment"},{"name":"ASST3","column_to_sort_by":"ASST3","type":"assessment"},{"name":"ASST4","column_to_sort_by":"ASST4","type":"assessment"},{"name":"ASST5","column_to_sort_by":"ASST5","type":"assessment"},{"name":"ASST6","column_to_sort_by":"ASST6","type":"assessment"},{"name":"ASST7","column_to_sort_by":"ASST7","type":"assessment"},{"name":"ASST8","column_to_sort_by":"ASST8","type":"assessment"},{"name":"ASST9","column_to_sort_by":"ASST9","type":"assessment"}]}],"type":"unit"}]},{"name":"PO2","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO3","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO4","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO5","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO6","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO7","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO8","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO9","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO10","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO11","column_to_sort_by":null,"type":"program_outcome"}]},{"name":"POGroup2","column_to_sort_by":null,"type":"1program_outcome_group"}]},{"name":"ProgramGroup2","column_to_sort_by":null,"type":"program_group"}]};
      
      var margin = {
          top: 20,
          right: 120,
          bottom: 20,
          left: 120
        },
        width = 2000 - margin.right - margin.left,
        height = 500 - margin.top - margin.bottom;
      
      var i = 0,
        duration = 750,
        root;
      
      var tree = d3.layout.tree()
        .size([height, width]);
      
      var diagonal = d3.svg.diagonal()
        .projection(function(d) {
          return [d.y, d.x];
        });
      
      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;
      root.x0 = height / 2;
      root.y0 = 0;
      
      function pageNodes(d, options) {
        if (d.children) {
          d.children.forEach(c => pageNodes(c, options));
          if (d.page && d.children.length > options.maxNode) {
            d.pages = {}
            const count = options.maxNode - 2;
            const l = Math.ceil(d.children.length / count);
            for (let i = 0; i < l; i++) {
              const startRange = i * count;
              const endRange = i * count + count;
              let pageNumber = i == 0 ? l - 1 : i - 1;
              d.pages[i] = d.children.slice(startRange, endRange);
              d.pages[i].unshift({
                ...d.pages[i][0],
                data: {
                  name: options.getLabel ? options.getLabel(pageNumber) : "..."
                },
                pageNumber,
                name: "..."
              })
      
              // console.log(i, d.pages[i]);
              pageNumber = i != (l - 1) ? i + 1 : 0;
              d.pages[i].push({
                ...d.pages[i][0],
                data: {
                  name: options.getLabel ? options.getLabel(pageNumber) : "..."
                },
                pageNumber,
                name: "..."
              });
            }
            d.children = d.pages[0];
            console.log(d.pages)
          }
        }
      }
      root.children.forEach(c => pageNodes(c, {
        maxNode: 8,
      }));
      
      function collapse(d) {
        if (d.children) {
          d._children = d.children;
          d._children.forEach(collapse);
          d.children = null;
        }
      }
      
      root.children.forEach(collapse);
      update(root);
      
      //svg.style("height", "500px");
      
      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 * 180;
        });
      
        // Update the nodes…
        var node = svg.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)
          .attr('stroke', function(d) {
            return d.color ? d.color : 'blue';
          })
          .style("fill", function(d) {
            return d._children ? "#ccc" : "#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", 1e-6);
      
        // Transition nodes to their new position.
        var nodeUpdate = node.transition()
          .duration(duration)
          .attr("transform", function(d) {
            return "translate(" + d.y + "," + d.x + ")";
          });
      
        nodeUpdate.select("circle")
          .attr("r", 10)
          .style("fill", function(d) {
            var collapseColor = d.color ? d.color : '#ccc';
            return d._children ? collapseColor : "#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) {
            return "translate(" + source.y + "," + source.x + ")";
          })
          .remove();
      
        nodeExit.select("circle")
          .attr("r", 1e-6);
      
        nodeExit.select("text")
          .style("fill-opacity", 1e-6);
      
        // Update the links…
        var link = svg.selectAll("path.link")
          .data(links, 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 diagonal({
              source: o,
              target: o
            });
          });
      
        // Transition links to their new position.
        link.transition()
          .duration(duration)
          .attr("d", diagonal);
      
        // Transition exiting nodes to the parent's new position.
        link.exit().transition()
          .duration(duration)
          .attr("d", function(d) {
            var o = {
              x: source.x,
              y: source.y
            };
            return diagonal({
              source: o,
              target: o
            });
          })
          .remove();
      
        // Stash the old positions for transition.
        nodes.forEach(function(d) {
          d.x0 = d.x;
          d.y0 = d.y;
        });
      }
      
      // Toggle children on click.
      function click(d) {
        if (d.hasOwnProperty('pageNumber')) {
          d.parent.children = d.parent.pages[d.pageNumber];
        } else if (d.children) {
          d._children = d.children;
          d.children = null;
        } else {
          d.children = d._children;
          d._children = null;
        }
        update(d);
      }
      

      在这里工作 example

      var treeData = {"name":"Program","column_to_sort_by":null,"type":"program","children":[{"name":"ProgramGroup1","column_to_sort_by":null,"type":"program_group","children":[{"name":"POGroup1","column_to_sort_by":null,"type":"1program_outcome_group","children":[{"name":"PO1","column_to_sort_by":null,"type":"program_outcome","children":[{"name":"Unit1","column_to_sort_by":"Unit1","children":[{"name":"UG1-LE","column_to_sort_by":null,"type":"unit_group","children":[{"name":"LE1","column_to_sort_by":"LE1","type":"learning_event"},{"name":"LE10","column_to_sort_by":"LE10","type":"learning_event"},{"name":"LE11","column_to_sort_by":"LE11","type":"learning_event"},{"name":"LE12","column_to_sort_by":"LE12","type":"learning_event"},{"name":"LE13","column_to_sort_by":"LE13","type":"learning_event"},{"name":"LE14","column_to_sort_by":"LE14","type":"learning_event"},{"name":"LE15","column_to_sort_by":"LE15","type":"learning_event"},{"name":"LE2","column_to_sort_by":"LE2","type":"learning_event"},{"name":"LE4","column_to_sort_by":"LE4","type":"learning_event"},{"name":"LE5","column_to_sort_by":"LE5","type":"learning_event"},{"name":"LE6","column_to_sort_by":"LE6","type":"learning_event"},{"name":"LE7","column_to_sort_by":"LE7","type":"learning_event"},{"name":"LE8","column_to_sort_by":"LE8","type":"learning_event"},{"name":"LE9","column_to_sort_by":"LE9","type":"learning_event"}]},{"name":"UG1-Assessments","column_to_sort_by":null,"type":"unit_group","children":[{"name":"ASST1","column_to_sort_by":"ASST1","type":"assessment"},{"name":"ASST10","column_to_sort_by":"ASST10","type":"assessment"},{"name":"ASST11","column_to_sort_by":"ASST11","type":"assessment"},{"name":"ASST13","column_to_sort_by":"ASST13","type":"assessment"},{"name":"ASST14","column_to_sort_by":"ASST14","type":"assessment"},{"name":"ASST15","column_to_sort_by":"ASST15","type":"assessment"},{"name":"ASST2","column_to_sort_by":"ASST2","type":"assessment"},{"name":"ASST3","column_to_sort_by":"ASST3","type":"assessment"},{"name":"ASST4","column_to_sort_by":"ASST4","type":"assessment"},{"name":"ASST5","column_to_sort_by":"ASST5","type":"assessment"},{"name":"ASST6","column_to_sort_by":"ASST6","type":"assessment"},{"name":"ASST7","column_to_sort_by":"ASST7","type":"assessment"},{"name":"ASST8","column_to_sort_by":"ASST8","type":"assessment"},{"name":"ASST9","column_to_sort_by":"ASST9","type":"assessment"}]}],"type":"unit"}]},{"name":"PO2","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO3","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO4","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO5","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO6","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO7","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO8","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO9","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO10","column_to_sort_by":null,"type":"program_outcome"},{"name":"PO11","column_to_sort_by":null,"type":"program_outcome"}]},{"name":"POGroup2","column_to_sort_by":null,"type":"1program_outcome_group"}]},{"name":"ProgramGroup2","column_to_sort_by":null,"type":"program_group"}]};
      
      var margin = {
          top: 20,
          right: 120,
          bottom: 20,
          left: 120
        },
        width = 2000 - margin.right - margin.left,
        height = 500 - margin.top - margin.bottom;
      
      var i = 0,
        duration = 750,
        root;
      
      var tree = d3.layout.tree()
        .size([height, width]);
      
      var diagonal = d3.svg.diagonal()
        .projection(function(d) {
          return [d.y, d.x];
        });
      
      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;
      root.x0 = height / 2;
      root.y0 = 0;
      
      function pageNodes(d, options) {
        if (d.children) {
          d.children.forEach(c => pageNodes(c, options));
          if (options.page && options.page(d) && d.children.length > options.maxNode) {
            d.pages = {}
            const count = options.maxNode - 2;
            const l = Math.ceil(d.children.length / count);
            for (let i = 0; i < l; i++) {
              const startRange = i * count;
              const endRange = i * count + count;
              let pageNumber = i == 0 ? l - 1 : i - 1;
              d.pages[i] = d.children.slice(startRange, endRange);
              d.pages[i].unshift({
                ...d.pages[i][0],
                data: {
                  name: options.getLabel ? options.getLabel(pageNumber) : "..."
                },
                pageNumber,
                name: "..."
              })
      
              // console.log(i, d.pages[i]);
              pageNumber = i != (l - 1) ? i + 1 : 0;
              d.pages[i].push({
                ...d.pages[i][0],
                data: {
                  name: options.getLabel ? options.getLabel(pageNumber) : "..."
                },
                pageNumber,
                name: "..."
              });
            }
            d.children = d.pages[0];
            console.log(d.pages)
          }
        }
      }
      root.children.forEach(c => pageNodes(c, {
        maxNode: 8,
        page: function(d) {
          return d.type == "unit_group";
        }
      }));
      
      function collapse(d) {
        if (d.children) {
          d._children = d.children;
          d._children.forEach(collapse);
          d.children = null;
        }
      }
      
      root.children.forEach(collapse);
      update(root);
      
      //svg.style("height", "500px");
      
      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 * 180;
        });
      
        // Update the nodes…
        var node = svg.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)
          .attr('stroke', function(d) {
            return d.color ? d.color : 'blue';
          })
          .style("fill", function(d) {
            return d._children ? "#ccc" : "#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", 1e-6);
      
        // Transition nodes to their new position.
        var nodeUpdate = node.transition()
          .duration(duration)
          .attr("transform", function(d) {
            return "translate(" + d.y + "," + d.x + ")";
          });
      
        nodeUpdate.select("circle")
          .attr("r", 10)
          .style("fill", function(d) {
            var collapseColor = d.color ? d.color : '#ccc';
            return d._children ? collapseColor : "#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) {
            return "translate(" + source.y + "," + source.x + ")";
          })
          .remove();
      
        nodeExit.select("circle")
          .attr("r", 1e-6);
      
        nodeExit.select("text")
          .style("fill-opacity", 1e-6);
      
        // Update the links…
        var link = svg.selectAll("path.link")
          .data(links, 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 diagonal({
              source: o,
              target: o
            });
          });
      
        // Transition links to their new position.
        link.transition()
          .duration(duration)
          .attr("d", diagonal);
      
        // Transition exiting nodes to the parent's new position.
        link.exit().transition()
          .duration(duration)
          .attr("d", function(d) {
            var o = {
              x: source.x,
              y: source.y
            };
            return diagonal({
              source: o,
              target: o
            });
          })
          .remove();
      
        // Stash the old positions for transition.
        nodes.forEach(function(d) {
          d.x0 = d.x;
          d.y0 = d.y;
        });
      }
      
      // Toggle children on click.
      function click(d) {
        if (d.hasOwnProperty('pageNumber')) {
          d.parent.children = d.parent.pages[d.pageNumber];
        } else if (d.children) {
          d._children = d.children;
          d.children = null;
        } else {
          d.children = d._children;
          d._children = null;
        }
        update(d);
      }
      

      在这里工作 example

      这篇关于d3.js Tree - 子节点的分页 v3.5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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