前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原 3D拓扑自动布局之Node.js篇

原 3D拓扑自动布局之Node.js篇

作者头像
HT_hightopo
发布2018-06-05 11:31:14
7840
发布2018-06-05 11:31:14
举报
文章被收录于专栏:hightopo

上篇将3D弹力布局的算法运行在Web Workers后台,这篇我们将进一步折腾,将算法运行到真正的后台:Node.js,事先申明Node.js篇和Web Workers篇一样,在这个应用场景下并不能提高性能,纯粹为了折腾好玩,当然也不会白玩,人生就在折腾中,只有折腾才能真正成长。

核心实现代码和Web Workers篇基本一致,唯一区别在于前后台交互的方式上,worker通过postMessage和addEventListener('message' 就可以发送和接收消息,对于真正分离前后台的Node.js自然没那么简单了,我采用了Socket.io通信框架,Socket.io让长连接通信变得无比简单,和Web Workers的通信几乎一样的容易了,Socket.io的用法下图一目了然:

Node.js后台代码如下,通过require引入HT和Socket.io相关类库,io = require('socket.io').listen(8036)构建出一个监听在8036端口的服务,通过io.sockets.on('connection'等着客户端页面来建立的socket通信,通过socket.on('moveMap',监听客户端发过来的图片节点拖拽变化信息进行同步,通过 socket.emit('result', result);发送自动布局算法的运算结果push到客户端。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

io = require( 'socket.io' ).listen(8036); ht = require( 'ht.js' ).ht; require( "ht-forcelayout.js" ); reloadModel = require( "util.js" ).reloadModel;      io.sockets.on( 'connection' , function  (socket) {         var  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();             }          });          socket.emit( 'result' , result);      };      forceLayout.start();        socket.on( 'moveMap' , function  (moveMap) {          dataModel.sm().cs();          for ( var  id in  moveMap){              var  data = dataModel.getDataById(id);              if (data){                  data.p3(moveMap[id]);                  dataModel.sm().as(data);              }          }          });      socket.on( 'reload' , function  (data) {          reloadModel(dataModel, data);        });           });

客户端的代码需要通过引入Socket.io客户端类库,通过socket = io.connect('http://localhost:8036/')链接服务器获得握手链接socket对象,剩下的代码就是同socket.emit发送客户端拖拽信息,以及socket.on监听服务器推送过来的自动布局结果:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

g3d.mi( function (evt){      if (evt.kind === 'betweenMove' ){                         moveMap = {};          g3d.sm().each( function (data){              if (data instanceof  ht.Node){                  moveMap[data._id] = data.p3();              }          });          socket.emit( 'moveMap' , moveMap);                     } });   socket = io.connect( 'http://localhost:8036/' );                              socket.on( 'result' , function  (result) {      for ( var  id in  result){          var  data = dataModel.getDataById([id]);          if (data && !g3d.isSelected(data)){              data.p3(result[id]);          }                     } });

几个注意点:

1、首选和Web Workers一样,跑在Node.js的类库肯定不能操作window和document之类的页面特定元素对象,从这点说很多考虑不周全的类库会把自己限制死只能在页面主线程运行,这点HT for Web考虑得很周到,不仅ht.js包括所有ht-forcelayout.js插件都是可运在Web Workers和Node.js的非GUI环境,因为我也常需要ht.js运行在后台直接将DataModel的数据和前台进行JSON的数据格式转换存储。

2、Util.js定义的reloadModel函数我增加了this.reloadModel = reloadModel;的逻辑,这样才能在Node.js后台代码reloadModel = require("../util.js").reloadModel; 这样的方式得到该函数进行调用,细节可以参考 http://nodejs.org/api/modules.html 的章节

3、这个例子是有缺陷的,以下视频播放过程你会发现,我打开了两个页面,这样就会有两个socket分别连接后台Node.js,而Node.js默认是单线程的,如果正在一个请求函数密集运算处理,则其他请求只能排队等待处理,这也是视频中我拖拽一个页面布局是,另一个页面无法操作的原因。当然你可以改进demo,采用http://nodejs.org/api/cluster.html的cluster方式,实现真正的后台多核任务处理

http://v.youku.com/v_show/id_XNjc1MjY2ODE2.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档