【问题标题】:D3js force layout destroy and resetD3js 强制布局销毁和重置
【发布时间】:2014-02-15 18:28:16
【问题描述】:

基于两个 D3 示例:力布局 (http://bl.ocks.org/mbostock/1095795) 和集群力布局 (http://bl.ocks.org/mbostock/1748247),我设法构建了一个力布局,其中有几个独立的重心点来控制节点在链接顶部的位置节点。

// Set up map
function map_init(){

    force = d3.layout.force()
        .nodes(nodes)
        .links(links)
        .size([width, height])
        .on("tick", tick);

    svg = d3.select("#map").append("svg")
        .attr("width", width)
        .attr("height", height);

    link = $map.selectAll(".link");
    node = $map.selectAll(".node");

    d3.json("graph.json", function(error, graph) {

        // set up nodes
        for( i = 0; i < graph.nodes.length; i++ ){          
            nodes.push( graph.nodes[i] );
        }

        // position nodes to three different gravity centres based on theme
        for( i = 0; i < nodes.length; i++ ){
            if ( nodes[i].theme == "theme1" ){ 
                nodes[i].cx = 100;
                nodes[i].cy = 100; 
            } else if ( nodes[i].theme == "theme2" ){ 
                nodes[i].cx = 300;
                nodes[i].cy = 300; 
            } else if ( nodes[i].theme == "theme3" ){ 
                nodes[i].cx = 500;
                nodes[i].cy = 500; 
            }   
        }

        // link nodes of the same theme
        theme1_nodes = nodes.filter(function(d){ return (d.theme == "theme1"); });
        theme2_nodes = nodes.filter(function(d){ return (d.theme == "theme2"); });
        theme3_nodes = nodes.filter(function(d){ return (d.theme == "theme3"); });
        for (i = 0; i < theme1_nodes.length-1; i++){
            links.push({ source: theme1_nodes[i], target: theme1_nodes[i+1] });
        }
        for (i = 0; i < theme2_nodes.length-1; i++){
            links.push({ source: theme2_nodes[i], target: theme2_nodes[i+1] });
        }
        for (i = 0; i < theme3_nodes.length-1; i++){
            links.push({ source: theme3_nodes[i], target: theme3_nodes[i+1] });
        }

        start();

    }); 

}

// Start
function start() {

  link = link.data(force.links(), function(d) { return d.source.id + "-" + d.target.id; });
  link.enter()
    .insert("svg:line")
        .attr("class", "link");
  link.exit()
        .remove();

  node = node.data(force.nodes(), function(d) { return d.id; });
  var nodeEnter = node.enter()
          .append("svg:g")
            .attr("class", "node");
        .on("click", map_nodeClick);
  node.exit().remove();

  // Enter node information
  nodeEnter.each(function(d) {
        theTitle = d3.select(this).append("svg:text")
        .attr("font-family", "Helvetica")
            .attr("class", "title")
        .text( d.title );
    });

    // More content to go into each node
    // .
    // .
    // .

  force.start();

}

// Tick
function tick(e) {

    node
      .each(gravity(.2 * e.alpha))
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })
      .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

    link.attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

}

// Gravity
function gravity(alpha) {

  return function(d) {
    d.y += (d.cy - d.y) * alpha;
    d.x += (d.cx - d.x) * alpha;
  };

}

// Set up when page first loads
map_init();

为了在不重新加载页面的情况下随时重置/重新启动强制布局,我将以下功能绑定到重置按钮:

// Remove force layout and data
function map_remove(){

    node.remove();
    link.remove();
    svg.remove();
    nodes = [];
    links = [];

}

// Reset button
$('a#reset').click(function(e){

    e.preventDefault();

    map_remove();
    map_init();

});

此网页显示在可供一群人访问的设备上。早上只加载一次,并在 iPad Safari 上运行了 12 个小时。理想情况下,节点之间的链接会根据用户输入(待实现)动态变化。除了部队布局之外,网页上还有其他信息。需要重新启动/重置强制布局而不重新加载页面的选项。

  1. 是否有内置方法来销毁 D3 强制布局及其数据?
  2. 目前这工作正常,因为没有创建额外的 DOM 元素,也没有从检查器中发现错误。但是我不确定如何检查所有 D3 对象是否已被清除/清空,因此没有存储/累积重复数据?
  3. 目前,由于某些原因,每次重置都会使节点越来越靠近地图中心。我是否遗漏了 map_remove() 函数中的某些内容?
  4. 完全重启 D3 强制布局是否会在任何时候提高浏览器的性能?即清理内存以绘制 SVG?

【问题讨论】:

    标签: javascript performance svg d3.js force-layout


    【解决方案1】:

    我做到了:

    nodeCircles = {};
    node.remove();
    link.remove();
    svg.clear();
    nodes = [];
    links = [];
    

    只需将其放入一个方法中,然后重新创建您的力和 svg。效果很好。

    【讨论】:

      【解决方案2】:
      1. 没有。您必须手动执行此操作。
      2. 您可以查看 DOM,但看起来您正在删除所有内容。
      3. 我猜这是因为您实际上并没有从强制布局中删除节点/链接。在某些时候,您已将变量 nodeslinks 提供给力布局。更改这些名称指向的内容(即[])不会更改强制布局中的引用。也就是说,数据对象仍然存在并被引用。有两种方法可以删除它们。您可以就地修改nodeslinks(例如使用.slice()),或者在强制布局中显式重置它们。

        nodes = []; links = []; force.nodes(nodes); force.links(links);

      4. 很难说没有具体的例子,但答案很可能是否定的。 Javascript 是垃圾收集器,因此手动进行应该不会产生影响。

      【讨论】:

      • 对不起,我对“......就地(例如使用 .slice())......”有点困惑。那应该是splice()吗?
      • 您可以同时使用这两种方法,具体取决于您想要做什么。
      猜你喜欢
      • 2019-09-02
      • 2018-12-26
      • 2015-12-04
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2019-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多