基于两个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小时.节点之间的链接理想地基于用户输入(将被实现)动态地改变.除了力布局外,网页上还有其他信息.需要重新启动/重置强制布局而不重新加载页面的选项.
>是否有内置方法来破坏D3力布局及其数据?
>目前这可以正常工作,因为没有创建额外的DOM元素,也没有从检查器中发现错误.但是我不确定如何检查所有D3对象是否已被清除/清空,因此没有存储/累积重复数据?
>目前,由于某些原因,每次重置都会使节点越来越靠近地图的中心.我错过了map_remove()函数中的某些内容吗?
>完全重启D3强制布局是否会在任何时候提高浏览器的性能?即清理用于绘制SVG的内存?