threejs建立地球

上个月底,在朋友圈看到一个号称“这多是地球上最美的h5”的分享,点进入后发现这个h5还很别致,思考了一会,决定要不高仿一个?css

到今天为止,高仿基本完成,html

除了手机端的media控制没有去兼容,其余的基本都给仿了。 那为了让你以为是高仿,最好使用chrome的手机调试模式进行访问。微信打开将听不见声音看不到视频... (后面再有时间看是否是仿的再进一步)web

之因此要仿它,由于以为这个h5还挺酷,想看看本身须要花多长时间找到并实现它的技术路径。chrome

需求分析

这个h5的主要玩法很简单:地球自转的时候会播放背景音乐(好比海浪声),为了找到这个声音是从哪一个地球上哪一个地方传来的,须要长按下方的按钮,这时地球会自动转动到目标地点,而后镜头拉近,穿过云层,最后你会看到和这段声音相关的视频内容;松开手以后,上面的过程会倒退回去,地球又开始自转,播放着下段神秘的背景音乐。canvas

我的以为这个设计仍是很新颖的,不是说用了3D的效果,而是将一个看起来很复杂的动画(从宇宙拉近到地表的过程),使用最基础的3D效果和其余一些常规的动画手法去实现,而且能流畅的运行在手机浏览器上。另外还有声音和视频的完美搭配,用户体验不错。

浏览器

反复观察,理清页面功能:微信

  1. 加载:加载进度百分比,饶椭圆轨道运行的小行星做为loading动画(这个动画我没有作)app

  2. 地球:3D球体,旋转入场动画,自转,漂移的云层,城市的坐标点,镜头的旋转与拉近,穿越云层动画

  3. 星空背景:静态星空背景图,动态(闪烁的)星星,划过的流星

  4. 隐藏的音频和视频:按内容(地理位置)划分的音频和视频内容

  5. 其余:操做指引示意动画,地球上方会显示当前城市的经纬度,“了解更多”的结语页面等

寻找技术路径

打开chrome inspect一下。

首先是这个地球,得看看它是真3D仍是假3D(由于不少3D效果是拿雪碧图作的,好比这里的旋转的3D飞机),结果找到了:

<div class="ns-webgl-page">
    <canvas width="750" height="1200" style="width: 375px; height: 600px;"></canvas>
</div>

而且在网站source文件中搜到了THREE,那就是threejs没跑了。

而后是那个穿越云层的效果,猜想多是GIF,多是SpriteSheet Animation,也有多是一段视频。可是考虑到这个穿越的动画能够正反双方播放,那么就极可能是是SpriteSheet Animation了,不然GIF或者视频文件须要两个动画方向各准备一份。这个从chrome debug工具的network下找到了证据—— 页面下载了一系列名为kf_cloud_0000X.jpg的图片文件。顺手就把它们down下来,备用。

再就是背景音乐和隐藏视频的问题,一样在network下,找到了两个文件,一个mp3一个mp4,每一个文件都包含了全部片断,就像是media的雪碧图,只在须要的时候控制播放对应片断而已。

其余的内容都没什么问题,CSS动画或者CANVAS都好作。那么到此,技术路径都清楚了,准备开始写代码。

难点突破

对于我而言,用threejs绘制地球可能会是难点,threejs没有用过,并且印象中对3D的东西,一直比较敬畏。若是3D的地球弄不出来,这个项目其余的都作完了,在浩瀚的宇宙中是怎么也找不到“声音来自何方”了。

OK,来看threejs怎么能弄出个地球来。(这个阶段并无开始项目代码,而是尽可能的在一个临时文件中进行涂鸦,快速随意的达到绘制出地球的目的就好了)

官网

对于新的技术,首先得看官网。这里并非来全面学习threejs的,而是抱着很强的目的性去实现特定功能,所以直接去示例中找,是否有相似实现能够借鉴。在官网首页中,经过缩略图,找到了下面三个关于地球的例子。

惋惜,貌似这里的例子都是一些产品应用,代码都是压缩过的。因而开始去寻找官方示例,最后在examples里找到了canvas_geometry_earth,最棒的是在github上有源码

示例代码

clone下threejs的项目代码,找到上面的示例文件。示例代码不到200行,阅读以后发现其实threejs和以前接触过的一些2D的游戏引擎(createjs,pixijs)等比较相似,都须要有场景(scene),要有渲染循环(render loop),在scene上添加对象(Mesh)或者是group;而Mesh由形状(Geometry)和材质(Material)组成,Material则又是由图片建立的纹理(Texture)而来。不一样的是,这里有相机(Camera),有光线(Light),还有一些一直都不明白的距离单位问题。

稍微改动一下示例代码,就能建立出来了earth。可是从使用的资源来看,只有一个地表纹理贴图(earth4.jpg),而xplan中还有3个关于earth的图片文件:

不肯定bump和spec是什么,个人思路是先在官方文档中找这些关键词,若是找不到,就加上threejs一块儿去作google。官网上找到了bump相关的东西,但帮助最大的是google出来的一篇详细的如何使用threejs建立earth的教程。(若是这个教程早点冒出来,也省了前面改示例代码的时间了。主要也源于对threejs不熟悉,没有想到哪些示例可能已经有不少教程了)

换上了earth4.jpg贴图以后:

earth_bump

了解到bumpmap:

Bump mapping is a technique to simulate bumps and wrinkles on the surface of an object. The result is an apparently bumpy surface rather than a smooth surface although the surface of the underlying object is not actually changed. I'm sorry, you can't tilt the camera to see 3D mountains with this technique. You can adjust the bump effect (how much the map affects lighting) with the bumpScaleparameter

threejs中bumpmap是调节对光线的感知,来令人能明显感受到不光滑的表面,而并无在mesh中添加起伏,即没有真的改变形状。

官方bumpmap示例效果图以下:

其实这里的earth_bump.jpg就是一个DEM,在threejs中称做bumpmap,在其余一些地方也有被叫作heightmap。即用灰度图表达高程,越黑表示高程越低,越亮表示高程越高。GIS专业中经常使用,unity3D中建立地形也会用到这个。

添加了earth_bump以后:

earth_spec

了解到了earth_spec.jpg是specular map,用来调节镜面反射的,这里主要是调节海洋对光线的反射,增长真实性。

添加了earth_spec以后:

漂移的云层

云层的添加, 前面的教程里已经很详细了,其实就是一个同心,半径大一点的球体而已。

添加了云层以后:

浮动的标签

xplan中地球表面有城市标签,会随着地球的自转而移动,同时又保持了水平的方向。google关键词:threejs floating label。因而找到:

 

 找到方向就好办,稍微参考一下官方API文档和找到的示例代码,可以很容易的在earth上添加上浮动标签。

小结

到这里,3D地球的绘制基本差很少了。虽然threejs是新东西,可是绝大部分功能都容易找到方向,而且改动一下示例代码都够快速的实现咱们想要的效果,所这个过程并不难。重点是如何在一个未知的领域内找到想要的东西,而且快速的为本身所用。

但过程当中我碰到一个性能问题,耽误了好久。xplan的页面在chrome的PC和手机模式都有近60的FPS,可是我建立的earth在PC有60,可是在手机模式却不到30!最后逐一调试代码,修改参数,花了很久才找到缘由:

renderer.setPixelRatio(window.devicePixelRatio)

threejs的示例代码中都有这么一行,就是这一行致使了个人代码比xplan的代码在手机上绘制的像素点翻倍,从而致使了性能成倍的降低。

另外,前面也提到,我对于3D框架中的距离单位和坐标问题,很模糊。因而这里,关于earth的大小,camera朝向,每一个城市标签的三维坐标和其余关与三维坐标的问题,我都硬抄了xplan的参数(幸亏他们的代码没有压缩...)。还有一个要认可的,就是地球后面的淡蓝色光晕效果,貌似用了一些高级的渲染技术,我也就硬搬了xplan这部分代码。

相关文章
相关标签/搜索