Throughout the last three months, I was quite fortunate to work for Freifunk on netjsongraph.js under the guidance of my mentor Federico Capoano. Thanks for this invaluable experience that I learned a lot of knowledge and use them in a practical project. Here is a summary of the work I have done during the Google Summer of Code (GSoC) 2017.
netjsongraph.js is a visualization library for NetJSON, a network topology data format. The main goal of netjsongraph.js may be concluded in below three lines (more details you can see in GSoC 2017-netjsongraph.js: visualization of NetJSON data):
- Apply the modern front-end development tools and add tests workflow (#1, #45)
- Rewrite it with WebGL (#11, #29, #39, #42, #47)
- Improve the performance (#41, #44, #46)
You can browse all examples on GitHub pages. Some screen shots of the application:
The force-directed layout is usually used to visualize network data. It offers insights on the relationships between nodes and links. The previous version of netjsongraph.js is implemented by d3 and it’s rendered using SVG. It would be very slow if there were thousands or ten of thousands nodes or links. So I have to embrace the WebGL speeded up by GPU to have a better performance.
I have recorded my work in the blog every milestone:
BTW, It’s a great management method to make members submit weekly reports and blog posts in Freifunk.
During the three months, there have been 116 commits from me. I created a big Pull Request include them:
Almost all goals have achieved:
- Published a minor version
- Improved development workflow
- Tests Added
- Refactored visualization by Three.js and d3-force
- Added more interaction like hover (show nodes tooltips), click (show nodes or links information panel), pan and zoom
- Improved performance
Especially on performance aspect, it runs efficiently on Chrome reached 60FPS under 5k nodes and 10k links. And if you don’t wanna animation, you can choose the static rendering layout.
I also encounter some challenges I never met before.
As you know, WebGL renders all objects in one canvas tag. How to bind events on every geometry? You should use the Ray casting. Raycasting is used for mouse picking (working out what objects in the 3d space the mouse is over) amongst other things. So you can know which geometry your mouse over and add some interaction effect.
There are thousands of objects and every object has several events you should handle, I had to develop an event controller to manage it.
The bottleneck in this visualizer is performance(#41). I tried many methods to improve it include:
However, the color of every node is different and the one link should highlight itself when it hovered, so the material should be independent and can not use in common.
Same problem with above. It’s not flexible to combine them to one mesh, different nodes and links should have different positions.
Make calculation before rendering, so there is no animation and repaint.
Web Workers is a simple means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface. So put static layout calculation into it will be efficient.
There are different complexity and cost in the different force-directed algorithm. The Force-Atlas2 algorithm has some benefits over the force layout implemented in d3-force. So current version may be refactored by an advanced algorithm in the future.
- Add optional geographic map (#40)
- Using Force-Atlas2 algorithm
More interactions and features should be added, and performance may be optimized by using new algorithm. I’d like to continue developing this project after GSoC.
In the end, thanks for the great patience and guidance from my mentors. Thanks for Google to provide me with this rare chance to contribute to an open source community together with awesome members from all over the world. I really appreciate this invaluable experience accumulated this summer and I believe it will have the profound impact on my career and life.
本作品采用知识共享 署名-非商业性使用-禁止演绎 4.0 国际 许可协议进行许可。