最近用d3js写了一个把树可视化的工具,但是遇到一个问题,当树的结点非常多的时候,加载整棵树会卡一段时间,体验不是很好,所以想是不是能用分帧加载的方法,不要一次加载整棵树,而是隔一段时间加载一部分。
这是老套路了,本来觉得应该挺简单的,但是网上查了半天也找到符合需求的文章,又去查API,发现也没有可用的。期间也发现了一个看起来可以用的,先贴一下链接:http://jsfiddle.net/cyril123/sef9udod/ 。但是当我用过才发现,这是个花架子,中看不中用,它的缺点是每次都要重新生成数据,数据量小的时候当然怎样都好,但是对于我当前要解决的问题并没有什么帮助。
看了一下源码,没看懂……有些关键代码不知道隐藏到什么地方去了,而且我只是想做个工具,不想研究太深。没办法,只能看看有没有什么黑科技了,一搬生成树的数据的时候,会有这样一个代码:
var tree = d3.layout.tree().size([width - 50,height - 50])
.separation(function(a,b){
return (a.parent == b.parent ? 1 : 2); });
var diagonal = d3.svg.diagonal()
.projection(function(d){
return [d.x, d.y]});
var svg = d3.select('#display').append('svg')
.attr('width',width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(0,10)');
var nodes = tree.nodes(target);
var node = svg.selectAll('.node')
.data(nodes)
.enter()
.append('g')
.attr('class','node')
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';})
其实我的目的呢,就是分步去执行代码中append(‘g’)以及后面一系列操作,但是这个操作d3js是不支持的,所以我把执行到enter()的结果打印出来,发现这是一个数组+一些其他额外的属性,之前尝试把数组中的数拆开,未果,最后想了个招,把这个数组中的每个元素,也就是每个结点都拿出来,用形成一堆数组,只不过这些数组中只有一个元素罢了,这样我虽然不知道这个源码怎么实现,但是我只要每次去调对应的函数就好了,因为我把这些属性都copy下来,形成一个新的对象了。也得亏是js这种原型模式,其他语言不一定会出现什么奇怪的bug……
最后贴一下代码:
var NODE_NUM = 10000;
var MAX_CHILD = 50;
var updateTimeout = null;
var Node = function() {
this.index = 0;
this.parent = {};
this.children = [];
this.history = "";
}
//随机生成一棵树
function generalRandomTreeObject(total_number, max_child, idx) {
var tree = {name:idx + 1};
if (total_number == 1) {
return tree;
}
tree.children = [];
total_number -= 1;
idx &#