想做一个主页,页面上有一个地球和云层的3D效果。想了下这个使用Three.js还是 蛮简单 的。首先给一个SphereGeometry加上地球纹理,再给另一个SphereGeometry加上透明的云层纹理,套在一起,加上动画就好了
效果预览(使用高清点的纹理图片效果应该会好很多):
首先定义场景等基本要素:
const WIDTH = document.body.clientWidth;
const HEIGHT = document.body.clientHeight;
//定义 scene, camera, render
let scene = new THREE.Scene();
//透视投影
let camera = new THREE.PerspectiveCamera(75, WIDTH/HEIGHT, 0.1, 2000);
//正射投影
//camera = new THREE.OrthographicCamera( WIDTH / -2, WIDTH / 2, HEIGHT / 2, HEIGHT / -2, 1, 2000 );
camera.position.z = 150;
//antialias 抗锯齿
let renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(WIDTH, HEIGHT);
document.querySelector('#container').appendChild(renderer.domElement);
导入纹理(这里返回的是Promise,便于使用async函数):
/**
* 导入纹理
* @param path
* @returns {Promise}
*/
function loadTexture(path){
return new Promise((resolve, reject)=>{
let loader = new THREE.TextureLoader();
loader.load(path, texture => {
resolve(texture);
} , ()=>{} , ()=>{reject('fail')});
});
}
发现现在的Three提供了THREE.Group对象,可以把多个Mesh进行组合,这样可以同时控制Mesh的位置:
//地球还包含云层
let earth = new THREE.Group();
加上地球和云层的纹理,由于云层纹理是一张透明的PNG图片,需要设置Mesh的transparent为true:
//地球
earth.position.z = 0;
let earthTexture = await loadTexture('img/earth.jpg');
let earthGeometry = new THREE.SphereGeometry( R_EARTH, 50, 50 );
let earthMaterial = new THREE.MeshBasicMaterial( { map: earthTexture, overdraw: 0.5 } );
let earthMesh = new THREE.Mesh( earthGeometry, earthMaterial );
earth.add( earthMesh );
//地球的云层
let cloudTexture = await loadTexture('img/clouds.png');
let cloudGeometry = new THREE.SphereGeometry( R_EARTH+5, 50, 50 );
let cloudMaterial = new THREE.MeshBasicMaterial( { map: cloudTexture, overdraw: 0.5, transparent: true} );
let cloudMesh = new THREE.Mesh( cloudGeometry, cloudMaterial );
earth.add( cloudMesh );
加上旋转动画:
function animateRunner(){
this.delta = 0;
this.run = function(){
earth.rotation.y -= 0.002;
requestAnimationFrame( this.run.bind(this) );
renderer.render( scene, camera );
}
}
动态效果(渣渣效果-_-||):