Chinaunix首页 | 论坛 | 博客
  • 博客访问: 938483
  • 博文数量: 110
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1997
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-15 22:39
个人简介

HT for Web 3D. HT for modern web and mobile app development. www.hightopo.com

文章分类

全部博文(110)

文章存档

2020年(1)

2018年(28)

2017年(21)

2016年(10)

2015年(28)

2014年(19)

2013年(3)

我的朋友

分类: HTML5

2014-02-20 19:19:36

2D拓扑的应用在电信网管和电力SCADA领域早已习以为常了,随着OpenGL特别是WebGL技术的普及,3D方式的数据可视化也慢慢从佛殿神堂步入了寻常百姓家,似乎和最近高档会所被整改为普通茶馆是一样的节奏。

 

3D呈现固然比2D方式更直观,但如果摆放图元布局却比2D麻烦,毕竟增加了一个维度,手工布局不如以前2D手工操作方便,因此3D的自动布局功能比2D凸显其重要性。最近玩了玩的弹力自动布局插件挺有意思,特别在平板上Touch方式拖拽三维空间图元节点时,对我这种控制欲较强者很有满足感。


 

弹力布局也不是啥新鲜玩意儿了,传统弹力布局算法都是采用通过CPU迭代运算的方式,对于海量数据特别是在纯客户端运算的方式肯定是不可行的,因此这些年也有很多采用GPU的方式进行并行计算的方式可极大提高性能,等OpenCL更成熟提供了WebCL的解决方案我再来张开这个话题。今天的话题采用的还是CPU,只不过我把自动布局的算法拉到了Web Worker来运算,纯属为了好玩实际意义不大,毕竟Worker运算结果还得不断序列化给GUI页面层,不断来回数据传输也挺耗性能,当然如果你让Worker运行一段时间,只把最终结果push回Web层进行呈现还是有点实际意义的,毕竟不用Worker时js单线程运行,对这种计算密集型的算法只会卡死界面无法进行其他业务操作。


 

以下是页面部分的代码,通过new Worker('workderjs')构建Worker后台运行对象,通过worker.addEventListener('message', ..)监听后台自动布局后派发的图元位置信息进行更新,通过worker.postMessage(info)发送界面拖拽图元位置变化信息。

 

Js代码  收藏代码
  1. function reload() {                      
  2.      var info = {  
  3.          A: parseInt($("A").value),   
  4.          B: parseInt($("B").value)  
  5.      };  
  6.      reloadModel(dataModel, info);  
  7.      worker.postMessage(info);  
  8.  }  
  9.   
  10.  function init() {          
  11.      dataModel = new ht.DataModel();                     
  12.      g3d = new ht.graph3d.Graph3dView(dataModel);   
  13.      toolbar = new ht.widget.Toolbar(items);  
  14.      borderPane = new ht.widget.BorderPane();  
  15.      borderPane.setTopView(toolbar);  
  16.      borderPane.setCenterView(g3d);         
  17.   
  18.      g3d.mi(function(evt){  
  19.          if(evt.kind === 'betweenMove'){                  
  20.              moveMap = {};  
  21.              g3d.sm().each(function(data){  
  22.                  if(data instanceof ht.Node){  
  23.                      moveMap[data._id] = data.p3();  
  24.                  }  
  25.              });  
  26.              worker.postMessage({moveMap: moveMap});                  
  27.          }  
  28.      });   
  29.   
  30.      worker = new Worker("worker.js");      
  31.      worker.addEventListener('message'function(e) {  
  32.          var info = e.data;  
  33.          for(var id in info.result){  
  34.              var data = dataModel.getDataById([id]);  
  35.              if(data && !g3d.isSelected(data)){  
  36.                  data.p3(info.result[id]);  
  37.              }                  
  38.          }    
  39.      });   
  40.   
  41.      reload();  
  42.  }  

     

以下是后台Work.js的代码,通过importScripts("ht.js")引入HT核心包,通过importScripts("ht-forcelayout.js")引入HT的弹力布局插件,通过importScripts("util.js")引入和页面代码共享的一些通用函数,通过self.postMessage({result: result})发送自动布局运算结果推送到页面,通过

self.addEventListener('message', ...)监听页面发过来的位置变化信息,从而实现了前后台的互通。

 

Js代码  收藏代码
  1. importScripts("ht.js");  
  2. importScripts("ht-forcelayout.js");  
  3. importScripts("util.js");  
  4.   
  5. ht = self.ht;  
  6. dataModel = new ht.DataModel();  
  7. forceLayout = new ht.layout.Force3dLayout(dataModel);  
  8.   
  9. forceLayout.onRelaxed = function(){      
  10.     var result = {};  
  11.     dataModel.each(function(data){  
  12.        if(data instanceof ht.Node){  
  13.            result[data._id] = data.p3();  
  14.        }   
  15.     });  
  16.     self.postMessage({result: result});  
  17. };  
  18. forceLayout.start();      
  19.   
  20. self.addEventListener('message'function(e) {  
  21.     var info = e.data;  
  22.     if(info.moveMap){  
  23.         dataModel.sm().cs();  
  24.         for(var id in info.moveMap){  
  25.             var data = dataModel.getDataById(id);  
  26.             if(data){  
  27.                 data.p3(info.moveMap[id]);  
  28.                 dataModel.sm().as(data);  
  29.             }  
  30.         }  
  31.     }  
  32.     else{  
  33.         reloadModel(dataModel, info);                   
  34.     }          
  35. }, false);  

 

以下为在Android平板上跑3D拓扑自动布局的效果,这个例子纯粹为了玩玩Web Workers,这样折腾性能并不会提高,甚至因为来回序列化更费性能,Web Worker可以使用的场景并不太多,比较适合纯数学运算的业务逻辑,同时还需要注意跑在Worker的代码是不能操作任何界面对象,例如window和document之类的对象。

 

下篇《3D拓扑自动布局之Node.js篇》我们再将算法移到Node.js端玩

 

阅读(2771) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~