当前位置:   article > 正文

Three.js 创建 3D 地球_threejs 地球

threejs 地球
# 实现效果 

# Threejs 基础概念简单介绍

Threejs和Webgl的关系

Three.js经常会和WebGL混淆, 但也并不总是,Three.js其实是使用WebGL来绘制三维效果的。WebGL是一个只能画点、线和三角形的非常底层的系统。想要用WebGL来做一些实用的东西通常需要大量的代码, 这就是Three.js的用武之地。它封装了诸如场景、灯光、阴影、材质、贴图、空间运算等一系列功能,让你不必要再从底层WebGL开始写起。

基础Threejs场景

一个最基础的Three.js程序包括渲染器(Renderer)、场景(Scene)、相机(Camera)、灯光(灯光),以及我们在场景中创建的物体(Earth)。

#入口文件

使用webpack打包,src/index.html是入口文件

文件列表

index.html
  1. <div id="loading">
  2. <div class="sk-chase">
  3. <div class="sk-chase-dot"></div>
  4. <div class="sk-chase-dot"></div>
  5. <div class="sk-chase-dot"></div>
  6. <div class="sk-chase-dot"></div>
  7. <div class="sk-chase-dot"></div>
  8. <div class="sk-chase-dot"></div>
  9. </div>
  10. <div>加载资源中...</div>
  11. </div>
  12. <div id="html2canvas" class="css3d-wapper">
  13. <div class="fire-div"></div>
  14. </div>
  15. <div id="earth-canvas"></div>
  • #loading: 加载中的loading效果

  • #earth-canvas:将canvas绘制到此dom下面

  • #html2canvas:将html转换成图片,显示地球标点

index.ts 

webpack 会将此文件打包成js,放进 index.html 中 

  1. import World from './world/Word'
  2. // earth-canvas
  3. const dom: HTMLElement = document.querySelector('#earth-canvas')
  4. // 将dom传进去
  5. new World({ dom, })

World.ts 创建3D世界 

  1. // 传入dom,创建出threejs场景、渲染器、相机和控制器。
  2. this.basic = new Basic(option.dom)
  3. this.scene = this.basic.scene
  4. this.renderer = this.basic.renderer
  5. this.controls = this.basic.controls
  6. this.camera = this.basic.camera
  1. // 传入dom,主要进行dom尺寸计算和管理resize事件。
  2. this.sizes = new Sizes({ dom: option.dom })
  3. this.sizes.$on('resize', () => {
  4. this.renderer.setSize(Number(this.sizes.viewport.width), Number(this.sizes.viewport.height))
  5. this.camera.aspect = Number(this.sizes.viewport.width) / Number(this.sizes.viewport.height)
  6. this.camera.updateProjectionMatrix()
  7. })
  1. // 传一个function,资源加载完成后会执行此function。
  2. this.resources = new Resources(async () => {
  3. await this.createEarth()
  4. // 开始渲染
  5. this.render()
  6. })
  1. // 地球相关配置
  2. type options = {
  3. data: {
  4. startArray: {
  5. name: string,
  6. E: number, // 经度
  7. N: number, // 维度
  8. },
  9. endArray: {
  10. name: string,
  11. E: number, // 经度
  12. N: number, // 维度
  13. }[]
  14. }[]
  15. dom: HTMLElement,
  16. textures: Record<string, Texture>, // 贴图
  17. earth: {
  18. radius: number, // 地球半径
  19. rotateSpeed: number, // 地球旋转速度
  20. isRotation: boolean // 地球组是否自转
  21. }
  22. satellite: {
  23. show: boolean, // 是否显示卫星
  24. rotateSpeed: number, // 旋转速度
  25. size: number, // 卫星大小
  26. number: number, // 一个圆环几个球
  27. },
  28. punctuation: punctuation,
  29. flyLine: {
  30. color: number, // 飞线的颜色
  31. speed: number, // 飞机拖尾线速度
  32. flyLineColor: number // 飞行线的颜色
  33. },
  34. }
  35. // 1.将earth中的group添加到场景中
  36. this.scene.add(this.earth.group)
  37. // 2.通过await init创建地球及其相关内容,因为创建一些东西需要时间,所以返回一个Promise
  38. await this.earth.init()
  39. // 3.地球创建完之后隐藏dom,添加一个事先定义好的类名,使用animation渐渐隐藏掉dom
  40. const loading = document.querySelector('#loading')
  41. loading.classList.add('out')
  1. // 1.将earth中的group添加到场景中
  2. this.scene.add(this.earth.group)
  3. // 2.通过await init创建地球及其相关内容,因为创建一些东西需要时间,所以返回一个Promise
  4. await this.earth.init()
  5. // 3.地球创建完之后隐藏dom,添加一个事先定义好的类名,使用animation渐渐隐藏掉dom
  6. const loading = document.querySelector('#loading')
  7. loading.classList.add('out')

#加载资源 

地球中需要若干个贴图,在创建地球前,先把贴图加载进来。 

Assets.ts 整理资源文件 

  1. /**
  2. * 资源文件
  3. * 把模型和图片分开进行加载
  4. */
  5. interface ITextures {
  6. name: string
  7. url: string
  8. }
  9. export interface IResources {
  10. textures?: ITextures[],
  11. }
  12. const filePath = './images/earth/'
  13. const fileSuffix = [
  14. 'gradient',
  15. 'redCircle',
  16. "label",
  17. "aperture",
  18. 'earth_aperture',
  19. 'light_column',
  20. 'aircraft'
  21. ]
  22. const textures = fileSuffix.map(item => {
  23. return {
  24. name: item,
  25. url: filePath + item + '.png'
  26. }
  27. })
  28. textures.push({
  29. name: 'earth',
  30. url: filePath + 'earth.jpg'
  31. })
  32. const resources: IResources = {
  33. textures
  34. }
  35. export {
  36. resources
  37. }
通过使用threejs提供的LoadingManager方法,
管理资源的加载进度,以及保存一个textures对象,
key为name,value为Texture对象

 #添加地球

图片

图片

  • earth:创建一个地球mesh,

    并赋予ShaderMaterial材质和贴上地球贴图,

    之后可以通过着色器动画实现地球扫光效果。

  • points:创建一个由points组成的包围球,

    放在外围。

  1. const earth_geometry = new SphereBufferGeometry(
  2. this.options.earth.radius,
  3. 50,
  4. 50
  5. );
  6. const earth_border = new SphereBufferGeometry(
  7. this.options.earth.radius + 10,
  8. 60,
  9. 60
  10. );
  11. const pointMaterial = new PointsMaterial({
  12. color: 0x81ffff, //设置颜色,默认 0xFFFFFF
  13. transparent: true,
  14. sizeAttenuation: true,
  15. opacity: 0.1,
  16. vertexColors: false, //定义材料是否使用顶点颜色,默认false ---如果该选项设置为true,则color属性失效
  17. size: 0.01, //定义粒子的大小。默认为1.0
  18. })
  19. const points = new Points(earth_border, pointMaterial); //将模型添加到场景
  20. this.earthGroup.add(points);
  21. this.options.textures.earth.wrapS = this.options.textures.earth.wrapT =
  22. RepeatWrapping;
  23. this.uniforms.map.value = this.options.textures.earth;
  24. const earth_material = new ShaderMaterial({
  25. // wireframe:true, // 显示模型线条
  26. uniforms: this.uniforms,
  27. vertexShader: earthVertex,
  28. fragmentShader: earthFragment,
  29. });
  30. earth_material.needsUpdate = true;
  31. this.earth = new Mesh(earth_geometry, earth_material);
  32. this.earth.name = "earth";
  33. this.earthGroup.add(this.earth);

完整代码下载  

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/665449
推荐阅读
相关标签
  

闽ICP备14008679号