如何使用d3js画分帧画一棵树
来源:互联网 发布:注会考试网络培训哪好 编辑:程序博客网 时间:2024/06/06 08:00
最近用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 += 1; var child_number = Math.floor(Math.random()*max_child + 1); child_number = Math.min(child_number, total_number); var child_counts = new Array(child_number); for (var i = 0;i < child_number; ++i) { child_counts[i] = Math.floor(Math.random()*total_number + 1); } child_counts.sort(); var selected_number = 0; for (var i = 0;i < child_number; i++) { var now_number = child_counts[i] - selected_number; now_number = Math.max(now_number, 1); if (total_number - now_number < child_number - i - 1) { now_number = total_number - (child_number - i - 1); } if (i == child_number - 1) { now_number = total_number; } var child = generalRandomTreeObject(now_number, max_child, idx); tree.children.push(child); total_number -= now_number; selected_number += now_number; idx += now_number; } return tree;}function drawTree(target, width, height, flag) { clearTimeout(self.updateTimeout); var ds = $('#display'); $('#display')[0].innerHTML = ""; console.log(ds); if (flag) { return; } 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 links = tree.links(nodes); ////---------------复制引用分帧加载--------------------- var node = svg.selectAll('.node') .data(nodes).enter(); var link = svg.selectAll('.link') .data(links) .enter(); var nodeSpliter = []; var linkSpliter = []; var addNodeOnceTime = 500; var addLinkOnceTime = 600; function autoOpenTree(pos,nodeAddCount, linkAddCount) { if(linkAddCount < link[0].length) { var ob1 = []; ob1.__proto__ = link.__proto__; for (var i = 0;i < addLinkOnceTime && linkAddCount < link[0].length; ++i) { var ob2 = []; ob2.__proto__ = link[0].__proto__; ob2.parentNode = link[0].parentNode; ob2.update = link[0].update; ob2.push(link[0][linkAddCount]); ob1.push(ob2); linkAddCount += 1; } linkSpliter.push(ob1); linkSpliter[pos].append('path') .attr('class','link') .attr('d', diagonal); } if (nodeAddCount < node[0].length) { var ob1 = []; ob1.__proto__ = node.__proto__; for (var i = 0;i < addNodeOnceTime && nodeAddCount < node[0].length; ++i) { var ob2 = []; ob2.__proto__ = node[0].__proto__; ob2.parentNode = node[0].parentNode; ob2.update = node[0].update; ob2.push(node[0][nodeAddCount]); ob1.push(ob2); nodeAddCount += 1; } nodeSpliter.push(ob1); var p = nodeSpliter[pos].append('g') .attr('class','node') .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')';}); p.append('circle') .attr('r',4.5) .attr('stroke','steelblue') .attr('stroke-width','1.5px'); p.append("text") .attr("dx", function(d) { return d.children ? 14 : 0; }) .attr("dy", 16) .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) .text(function(d) { return d.name; }); } if(linkAddCount < link[0].length || nodeAddCount < node[0].length) { self.updateTimeout=setTimeout(function(){ autoOpenTree(pos + 1,nodeAddCount, linkAddCount); }, 30); } } autoOpenTree(0,0, 0); //--------正常画树方法------------------ // var link = svg.selectAll('.link') // .data(links) // .enter() // .append('path') // .attr('class','link') // .attr('d', diagonal); // var node = svg.selectAll('.node') // .data(nodes) // .enter() // .append('g') // .attr('class','node') // .attr('transform', function(d) {return 'translate(' + d.x + ',' + d.y + ')';}) // node.append('circle').attr('r',4.5); // node.append("text") // .attr("dx", function(d) { return d.children ? 14 : 0; }) // .attr("dy", 16) // .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) // .text(function(d) { return d.name; });}function test() { var source_tree = generalRandomTreeObject(NODE_NUM,MAX_CHILD,0); $(document).ready(function(){ drawTree(source_tree, 1000, 600); $('#btn_random').click(function(){ source_tree = generalRandomTreeObject(NODE_NUM,MAX_CHILD, 0); drawTree(source_tree, 1000, 600); }); });}test();
html代码也贴一下好了:
<!Doctype html><html xmlns:svg="http://www.w3.org/2000/svg"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta property="qc:admins" content="465267610762567726375" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>tree view</title> </head> <div> <button type='button' id='btn_random' style='width:100px;height: 33px'>draw new tree</button> <!-- <button type='button' id='btn_next' style='width:100px;height: 33px'>next</button> --> </div> <div name='all' id='display'> </div> <style> .node circle { fill: #fff; stroke: steelblue; stroke-width: 1.5px; } .node { font: 12px sans-serif; } .link { fill: none; stroke: #ccc; stroke-width: 1.5px; } </style> <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" type="text/javascript"></script> <script type="text/javascript" src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script type="text/javascript" src="framing_load_tree.js"></script></html>
0 0
- 如何使用d3js画分帧画一棵树
- D3js
- d3js+svg
- php d3js
- d3js比例尺
- Data Driven Document - D3js
- D3js--数据绑定更新
- d3js svg:text
- D3js-SVG简单初步
- D3js-绘制SVG
- D3js-API介绍【中】
- D3js-API介绍【英】
- D3js-值域渐变地图
- D3js-堆栈图
- d3js画矩形图
- d3js完整柱形图
- d3js的初接触
- d3js之弦图
- Spring学习笔记(网易博客整理版本)
- JSTL自定义标签
- Java 8 中的 Streams API 详解
- HLSL内置函数,及HLSL与GLSL的对应函数
- Tomcat配置远程调试端口
- 如何使用d3js画分帧画一棵树
- ffmpeg常用的头文件
- mybits中# $的区别
- Observer模式
- 'my_templatetag' is not a registered tag library.
- 0506
- MySQL修改密码
- Python字符串操作
- Lock框架简介