从0.5开始撸一个太阳系演示系统

3,841 阅读3分钟

大家好,这里是小呦,一个前端开发者。

作为有着一个酷炫3d梦的程序员,终于,在前段时间,接到了一个跟3d相关的小单子 — 开发一个太阳系介绍系统,大致要求如下:

  1. 需要是一个客户端,能在win系统下运行
  2. 显示太阳系模型,需要放大缩小旋转,点击行星可以显示详细资料以及对应的卫星轨迹图
  3. 关闭的时候能够记录上一次打开的行星

其实总体总结下来,实现难度并不是很大,更多的是显示效果以及交互效果上的一个显示,以及客户端打包。最终采用的技术框架是 Electron + Threejs + Jquery(没想到吧!)。多说无益,先上开发完的成果。

image.png image.png image.png picgo.zzuzsj.cn/Solar演示.mp4

整体开发周期大概花了5天左右,大部分事件都在优化细节和交互,显示效果方面的话由于没有提供设计,所以基本保留原样的素材做展示的。

大致总结一下开发过程中的复杂点:

  1. 自由旋转缩放的同时又需要悬浮暂停以及点击进入

    这个需求大致就是说,用户希望能够拖拽、缩放场景的同时,如果鼠标悬浮到行星上,整个动画能够暂停,让用户能够更舒服的点击进入行星界面。

    这个对于本次开发的困难点在于,缩放、拖拽等交互是通过three-trackballcontrols来实现的,因为快捷方便,但是美中不足的是,这个库也将mouseMove、mouseEnter等事件阻止默认事件了,导致监听不了renderer.element的mousemove事件。

    那既然知道症结了,先将库的dist文件复制下来之后,在mouseMove和mouseEnter时间里面,增加判断条件,如果判断条件生效了就不触发control的后续事件,便于自定义操作。

    image.png check条件可以从control实例生成的时候传入,这样有利于复用。那现在既然事件已经能监听到了,怎么获取到当前renderer场景中被点击的是哪个元素呢?

    这里就可以介绍了threejs的一个概念 — raycaster。在canvas中是判断当前点(x,y)所在位置是什么元素,而在3d场景里,则是判断(x,y)这条射线都穿过了哪几个模型,然后按照z的值从高到低排序,就是点击位置所对应的元素了。

    image.png 然后获取元素之后,只要进行场景切换就可以了,Yahoo!

  2. 动画的暂停和播放

    我们用的是tween.js来做交互动画的缓动效果,而tweenjs其实一直存在这个令人诟病的问题,就是它的暂停是真的不好用 Orz。

    因为tweenjs是按照时间戳的差距作为动画时间参数的计算依据,这就是说,tween动画被暂停之后,过一段时间再被开始,那就会出现跳变。

    有没有什么好的方法呢,哎,只能再次魔改一下了。

    image.png 手动增加tempPause和tempStart方法,用来做一个临时暂停和开始的功能,Yahoo!

  3. electron的打包问题

    这个问题比较简单,方案的选择而已,找一个比较舒服的打包方案。这里给大家推荐electron的经典打包库 — electron-builder

总体来说,这算是一个比较初级的3d场景代码,但是总体效果也还挺不错。包括交付之后,甲方爸爸也觉得做的质量和细节程度还是可以的,被肯定了很开心,也分享一下开发过程中自己的一些解决方案。

开发总是通过不同的项目需求不断成长的,记录和分享自己的成果也总是有趣的。大家如果有其他问题,也可以私聊问我,如果有开发需求的,也可以聊聊~See U.