2D拓扑的应用在电信网管和电力SCADA领域早已习以为常了,随着OpenGL特别是WebGL技术的普及,3D方式的数据可视化也慢慢从佛殿神堂步入了寻常百姓家,似乎和最近高档会所被整改为普通茶馆是一样的节奏。
3D呈现固然比2D方式更直观,但如果摆放图元布局却比2D麻烦,毕竟增加了一个维度,手工布局不如以前2D手工操作方便,因此3D的自动布局功能比2D凸显其重要性。最近玩了玩HT的弹力自动布局插件挺有意思,特别在平板上Touch方式拖拽三维空间图元节点时,对我这种控制欲较强者很有满足感。
弹力布局也不是啥新鲜玩意儿了,传统弹力布局算法都是采用通过CPU迭代运算的方式,对于海量数据特别是在纯客户端运算的方式肯定是不可行的,因此这些年也有很多采用GPU的方式进行并行计算的方式可极大提高性能,等OpenCL更成熟HT for Web提供了WebCL的解决方案我再来张开这个话题。今天的话题采用的还是CPU,只不过我把自动布局的算法拉到了Web Worker来运算,纯属为了好玩实际意义不大,毕竟Worker运算结果还得不断序列化给GUI页面层,不断来回数据传输也挺耗性能,当然如果你让Worker运行一段时间,只把最终结果push回Web层进行呈现还是有点实际意义的,毕竟不用Worker时js单线程运行,对这种计算密集型的算法只会卡死界面无法进行其他业务操作。
以下是页面部分的代码,通过new Worker('workderjs')构建Worker后台运行对象,通过worker.addEventListener('message', ..)监听后台自动布局后派发的图元位置信息进行更新,通过worker.postMessage(info)发送界面拖拽图元位置变化信息。
function reload() { var info = { A: parseInt($("A").value), B: parseInt($("B").value) }; reloadModel(dataModel, info); worker.postMessage(info); } function init() { dataModel = new ht.DataModel(); g3d = new ht.graph3d.Graph3dView(dataModel); toolbar = new ht.widget.Toolbar(items); borderPane = new ht.widget.BorderPane(); borderPane.setTopView(toolbar); borderPane.setCenterView(g3d); g3d.mi(function(evt){ if(evt.kind === 'betweenMove'){ moveMap = {}; g3d.sm().each(function(data){ if(data instanceof ht.Node){ moveMap[data._id] = data.p3(); } }); worker.postMessage({moveMap: moveMap}); } }); worker = new Worker("worker.js"); worker.addEventListener('message', function(e) { var info = e.data; for(var id in info.result){ var data = dataModel.getDataById([id]); if(data && !g3d.isSelected(data)){ data.p3(info.result[id]); } } }); reload(); }
以下是后台Work.js的代码,通过importScripts("ht.js")引入HT核心包,通过importScripts("ht-forcelayout.js")引入HT的弹力布局插件,通过importScripts("util.js")引入和页面代码共享的一些通用函数,通过self.postMessage({result: result})发送自动布局运算结果推送到页面,通过
self.addEventListener('message', ...)监听页面发过来的位置变化信息,从而实现了前后台的互通。
importScripts("ht.js"); importScripts("ht-forcelayout.js"); importScripts("util.js"); ht = self.ht; dataModel = new ht.DataModel(); forceLayout = new ht.layout.Force3dLayout(dataModel); forceLayout.onRelaxed = function(){ var result = {}; dataModel.each(function(data){ if(data instanceof ht.Node){ result[data._id] = data.p3(); } }); self.postMessage({result: result}); }; forceLayout.start(); self.addEventListener('message', function(e) { var info = e.data; if(info.moveMap){ dataModel.sm().cs(); for(var id in info.moveMap){ var data = dataModel.getDataById(id); if(data){ data.p3(info.moveMap[id]); dataModel.sm().as(data); } } } else{ reloadModel(dataModel, info); } }, false);
以下视频为在Android平板上跑3D拓扑自动布局的效果,这个例子纯粹为了玩玩Web Workers,这样折腾性能并不会提高,甚至因为来回序列化更费性能,Web Worker可以使用的场景并不太多,比较适合纯数学运算的业务逻辑,同时还需要注意跑在Worker的代码是不能操作任何界面对象,例如window和document之类的对象。
下篇《3D拓扑自动布局之Node.js篇》我们再将算法移到Node.js端玩
http://v.youku.com/v_show/id_XNjc1MjYzODg4.html
相关推荐
8. **性能优化**:由于拓扑图可能包含大量节点和连接,优化渲染性能是必要的,可能采用分层渲染、懒加载策略或使用Web Workers来提高响应速度。 9. **源码解析**:学习这个实例的源码,可以帮助你深入理解如何在...
这可能包括使用Web Workers进行离线计算,使用适当的缓存策略,以及优化渲染算法以减少重绘。 6. **可扩展性**:一个优秀的拓扑图例子应具备良好的可扩展性,允许添加新的功能或适配不同的数据源。 7. **API和工具...
这可能包括虚拟化(只渲染可视区域的节点)、懒加载和使用Web Workers进行计算。 9. **状态管理**:当拓扑图的数据需要在多个组件之间共享时,可以使用Redux、MobX或其他状态管理工具来协调状态。 10. **测试**:...
3. 使用Web Workers:将计算密集型任务移到Web Workers中,避免阻塞主线程。 总的来说,JS插件绘制树状图是数据可视化的强大工具,能够帮助我们有效地理解和呈现复杂的关系网络。正确选择和使用这些插件,可以让...
可以通过减少不必要的计算,使用CSS3硬件加速属性,或者使用Web Workers进行后台处理来优化。 8. **浏览器兼容性**:虽然现代浏览器对JavaScript和CSS3支持良好,但为了确保广泛的用户兼容性,可能需要使用像...
拓扑布局算法 为了适应不同复杂度的家谱,`ftree.js` 实现了多种布局算法。这些算法考虑了节点数量、层次关系以及屏幕空间,确保家谱的清晰性和可读性。用户可以选择合适的布局方式,或者根据需求实现自己的布局...
- HTML5的新特性:如canvas用于绘制图形,web storage和IndexedDB提供本地数据存储,Web Workers提升后台处理能力等。 在实际应用中,开发者可能会使用HTML5创建基于云的应用,利用云池提供的资源进行动态部署和...