接上篇,已經搭建好前端代碼框架,本文開始進行前端代碼的開發css
準備工做html
地球採用球體+蒙皮的方式實現,貼圖來自echarts: https://www.echartsjs.com/examples/data-gl/asset/world.topo.bathy.200401.jpg,下載貼圖jpg文件,存放至image文件夾,命名爲world.jpg前端
1 html模板 index.htmlnpm
在public文件夾中建立index.html,修改文件內容爲json
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>新冠疫情感染數</title> 7 <style> 8 *{ 9 padding:0; 10 margin:0 11 } 12 .container { 13 overflow: hidden; 14 position: fixed; 15 top: 0; 16 left: 0; 17 right:0; 18 bottom: 0; 19 display: flex; 20 flex-direction: row; 21 margin: 0 auto; 22 } 23 </style> 24 <script src="https://cdn.bootcss.com/lodash.js/4.17.15/lodash.min.js"></script> 25 </head> 26 <body> 27 <div class="container"></div> 28 </body> 29 <script> 30 // 調用組件 31 VDEarth.init({container:document.querySelector('.container')}); 32 </script> 33 </html>
2 主文件VDEarth.js瀏覽器
建立一個VDEarth類,構造屬性,方法app
class VDEarth{ constructor() { this.scene = null; this.camera = null; this.renderer = null; this.textrue = null; this.font = null; this.light = null; this.controls = null; this.contentWidth = 0; this.contentHeight = 0; this.options={} } init(opt = {}) {} } export default VDEarth;
修改初始化方法initecharts
因爲地球貼圖圖片較大,這裏在初始化的時候進行加載,加載完成後回調場景, 相機,渲染器,燈光,控制器,建立模型,動態更新等方法,具體實現參考後面地球實現章節。框架
1 init(opt = {}) { 2 var self = this; 3 // 合併用戶配置屬性 4 _.merge(this.options, opt); 5 6 // 獲取容器的寬高 7 this.contentWidth = this.options.container.offsetWidth; 8 this.contentHeight = this.options.container.offsetHeight; 9 // 加載貼圖 10 let globeTextureLoader = new TextureLoader(); 11 globeTextureLoader.load('./images/world.jpg', function (textrue) { 12 self.textrue = textrue; 13 // 初始化渲染器 14 initRenderer.call(self); 15 // 初始化舞臺 16 initScene.call(self); 17 // 初始化相機 18 initCamera.call(self); 19 // 初始化燈光 20 initLight.call(self); 21 // 初始化控制器 22 initControls.call(self); 23 // 初始化模型 24 initObj.call(self); 25 // 播放 26 animate.call(self); 27 }); 28 }
3 組件入口index.jsdom
調用VDEarth類,export一個初始化的方法供頁面調用
1 import VDEarth from './VDEarth'; 2 3 var myVDEarth = new VDEarth(); 4 export function init(opt) { 5 return myVDEarth.init(opt); 6 }
4 組件初始化
建立場景
VDEarth.js中添加私有方法
// 初始化場景 function initScene() { this.scene = new Scene(); }
建立渲染器
VDEarth.js中添加私有方法
// 初始化渲染器 function initRenderer() { this.renderer = new WebGLRenderer({ antialias: true }); this.renderer.setSize(this.contentWidth, this.contentHeight); this.options.container.appendChild(this.renderer.domElement); }
建立相機
VDEarth.js中添加私有方法
// 初始化照相機 function initCamera() { this.camera = new PerspectiveCamera(50,this.contentWidth / this.contentHeight,1,2000); this.camera.up.x = 0; this.camera.up.y = 1; this.camera.up.z = 0; this.camera.position.x = 0; this.camera.position.y = 0; this.camera.position.z = 500; this.camera.lookAt(0, 0, 0); }
建立燈光
VDEarth.js中添加私有方法
// 初始化燈光 function initLight() { // 天然光 this.scene.add(new AmbientLight(0xffffff)); }
建立控制器
VDEarth.js中添加私有方法,建立一個盤旋控制器
// 盤旋控制器 function initControls() { this.controls = new OrbitControls(this.camera, this.renderer.domElement); // 若是使用animate方法時,將此函數刪除 // 使動畫循環使用時阻尼或自轉 意思是否有慣性 this.controls.enableDamping = true; //動態阻尼係數 就是鼠標拖拽旋轉靈敏度 //controls.dampingFactor = 0.25; //是否能夠縮放 this.controls.enableZoom = true; //是否自動旋轉 this.controls.autoRotate = false; //是否容許旋轉 this.controls.enableRotate = true; //設置相機距離原點的最近距離 this.controls.minDistance = 20; //設置相機距離原點的最遠距離 this.controls.maxDistance = 1000; //是否開啓右鍵拖拽 this.controls.enablePan = false; }
建立實時更新方法
VDEarth.js增長私有方法
// 實時更新 function animate() { //更新控制器 this.controls.update(); render.call(this); requestAnimationFrame(animate.bind(this)); }
地球的實現
地球採用球體+蒙皮的方式實現,貼圖來自echarts: https://www.echartsjs.com/examples/data-gl/asset/world.topo.bathy.200401.jpg,下載貼圖jpg文件
建立地球模型
建立材質 - material.js
建立方法createGlobeMat 接受一個蒙皮的參數 textrue
import { MeshStandardMaterial, PointsMaterial, MeshPhongMaterial, DoubleSide, MeshBasicMaterial, } from 'three'; class material { constructor() {} createGlobeMat(texture) { let mat = new MeshStandardMaterial({ map: texture, }); return mat; } }
建立geometry -geometry.js
建立一個球體,createGlobeGeom接受一個size屬性,用來定義地球的半徑
class vdGeom { constructor() {} createGlobeGeom(size) { let geom = new SphereGeometry(size, 200, 200); return geom; } }
建立地球對象- model.js
一個threejs的模型的對象,包含materail和geometry,這裏引入前面的geometry.js 和material.js
1 import { Mesh, Points } from 'three'; 2 import material from './material'; 3 import geometry from './geometry'; 4 class mesh { 5 constructor() { 6 this.vdGeom = new geometry(); 7 this.vdMaterial = new material(); 8 } 9 createGlobe(size,textrue) { 10 let vdGeom = this.vdGeom.createGlobeGeom(size); 11 let vdMaterial = this.vdMaterial.createGlobeMat(textrue); 12 return new Mesh(vdGeom, vdMaterial); 13 } 14 } 15 export default mesh;
調用建立地球隊形-VDEarth.js
新增私有方法 initObj,初始化地球模型的加載
function initObj() { let self = this; let fontloader = new FontLoader(); // 建立地球模型組 this.baseGroup = new Group(); // 建立地球 this.radius = minSize(this.contentWidth, this.contentHeight) * 0.2; let globalMesh = new model().createGlobe(this.radius, this.textrue); this.baseGroup.add(globalMesh); // 添加到場景 this.scene.add(this.baseGroup); }
修改init方法,增長initObj的調用
init(opt = {}) { var self = this; // 合併用戶配置屬性 _.merge(this.options, opt); // 獲取容器的寬高 this.contentWidth = this.options.container.offsetWidth; this.contentHeight = this.options.container.offsetHeight; // 加載貼圖 let globeTextureLoader = new TextureLoader(); globeTextureLoader.load('./images/world.jpg', function (textrue) { self.textrue = textrue; // 初始化渲染器 initRenderer.call(self); // 初始化舞臺 initScene.call(self); // 初始化相機 initCamera.call(self); // 初始化燈光 initLight.call(self); // 初始化控制器 initControls.call(self); // 初始化模型 initObj.call(self); . . . }); }
而後一個簡單的地球就實現了,npm run start ,打開瀏覽器就能夠看到一個3D地球,能夠經過鼠標進行拖拽,旋轉等操做
加點佐料
這裏地球是靜止的,加上地球自轉效果
修改VDEarth.js 內 的animate方法,增長地球自轉的代碼
// 實時更新 function animate() { //更新控制器 this.controls.update(); render.call(this); // 地球自轉 this.baseGroup.rotation.y -= 0.002; requestAnimationFrame(animate.bind(this)); }
刷新下瀏覽器,地球就能夠轉動起來了
文內未說明import的模塊,能夠參照上篇裏的環境搭建的pagekage.json , npm 安裝響應的組件
相關連接
從0開始疫情3D地球 - 3D疫情地球VDEarth - 1- 引言
從0開始疫情3D地球 - 3D疫情地球VDEarth - 2 - 前端代碼構建
從0開始疫情3D地球 - 3D疫情地球VDEarth - 3 - 3D地球組件實現(1)
從0開始疫情3D地球 - 3D疫情地球VDEarth - 4 - 3D地球組件實現(2)