ThreeJS 制作地球
环境
- ThreeJS 107版本
- three.min.js
- OrbitControls.js
- 深空背景图片 大小4036*1808
- 地球贴图 大小2048*1024 边幅以东西经180度为界限
说明
原本我们GIS使用的是cesiumJS开发的三维,但如果仅仅作为前端,大屏展示三维地球效果,cesiumJS显得过于厚重。故非强GIS功能,我们探索了ThreeJS。
解决方案
- 获取地球容器
//获取地球容器
dom = document.getElementById('divEarth');
dom.style.width = '100%';
dom.style.height = '100%';
- 添加深空背景
var _imgSky = "assets/images/earth_bg.jpg";
dom.style.background = "url(" + _imgSky + ") no-repeat center center";
dom.style.backgroundColor = "#00000000";
- 初始化场景,并设置场景光线
// 初始化场景
scene = new THREE.Scene();
// 设置光线
scene.add(new THREE.HemisphereLight('#ffffff', '#ffffff', 1));
- 设置相机
// 初始化相机
camera = new THREE.PerspectiveCamera(20, dom.clientWidth / dom.clientHeight, 1, 100000);
// 设置相机位置
camera.position.set(0, 0, 200);
- 初始化渲染
renderer = new THREE.WebGLRenderer({
alpha: true, //是否透明
antialias: true //抗锯齿
});
renderer.autoClear = false;
// 设置窗口尺寸
renderer.setSize(dom.clientWidth, dom.clientHeight);
dom.appendChild(renderer.domElement);
- 初始化轨道控制器
这里需要先引入js包(OrbitControls.js)
// 初始化控制器
orbitcontrols = new THREE.OrbitControls(camera, renderer.domElement);
// 使动画循环使用时阻尼或自转 意思是否有惯性
orbitcontrols.enableDamping = true;
- 创建地球对象
// 定义地球材质
var earthTexture = THREE.ImageUtils.loadTexture("assets/images/starry_sky_bg.jpg", {}, function () {
renderer.render(scene, camera);
});
// 创建地球
earthBall = new THREE.Mesh(new THREE.SphereGeometry(30, 50, 50), new THREE.MeshBasicMaterial({
map: earthTexture
}));
earthBall.layers.set(0);
//添加到场景
scene.add(earthBall);
- 最后加上渲染
render();
// 执行函数
function render() {
if (handle) {
cancelAnimationFrame(handle);
}
renderer.clearDepth();
//自转,自转速度(正数自西向东转,负数为逆向)
scene.rotation.y += 0.01;
renderer.render(scene, camera);
orbitcontrols.update();
handle = requestAnimationFrame(render);
}
附上接口源码
var ThreeJSEarth = function (_domID, _earthOptions) {
var scene, renderer, camera, orbitcontrols;
var earthBall;//地球实体
var dom, handle;//容器,定时器动画句柄
/**
* 初始化地球,对象创建时自动调用
*/
(function init() {
//获取地球容器
dom = document.getElementById(_domID);
dom.style.width = '100%';
dom.style.height = '100%';
var _imgSky = _earthOptions.imgSky ? _earthOptions.imgSky : "";
dom.style.background = "url(" + _imgSky + ") no-repeat center center";
dom.style.backgroundColor = "#00000000";
// 初始化场景
scene = new THREE.Scene();
// 初始化相机
camera = new THREE.PerspectiveCamera(20, dom.clientWidth / dom.clientHeight, 1, 100000);
// 设置相机位置
camera.position.set(0, 0, _earthOptions.cameraZ ? _earthOptions.cameraZ : 200);
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.autoClear = false;
// 设置窗口尺寸
renderer.setSize(dom.clientWidth, dom.clientHeight);
// 初始化控制器
orbitcontrols = new THREE.OrbitControls(camera, renderer.domElement);
// 使动画循环使用时阻尼或自转 意思是否有惯性
orbitcontrols.enableDamping = true;
//动态阻尼系数 就是鼠标拖拽旋转灵敏度
// orbitcontrols.dampingFactor = 0.2;
dom.appendChild(renderer.domElement);
// 设置光线
scene.add(new THREE.HemisphereLight('#ffffff', '#ffffff', 1));
// 定义地球材质
var earthTexture = THREE.ImageUtils.loadTexture(_earthOptions.imgEarth ? _earthOptions.imgEarth : "404.jpg", {}, function () {
renderer.render(scene, camera);
});
// 创建地球
earthBall = new THREE.Mesh(new THREE.SphereGeometry(_earthOptions.earthBallSize, 50, 50), new THREE.MeshBasicMaterial({
map: earthTexture
}));
earthBall.layers.set(0);
scene.add(earthBall);
// this.renderEarthByRender();
render();
})();
// 执行函数
function render() {
if (handle) {
cancelAnimationFrame(handle);
}
renderer.clearDepth();
//自转
scene.rotation.y += _earthOptions.autorotationSpeed ? _earthOptions.autorotationSpeed : 0;
renderer.render(scene, camera);
orbitcontrols.update();
handle = requestAnimationFrame(render);
}
// 窗口resize事件
window.onresize = function () {
// 重新初始化尺寸
camera.aspect = dom.clientWidth / dom.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(dom.clientWidth, dom.clientHeight)
}
}
调用方式
//初始化
function initThree() {
var earthOptions = {
//imgEarth: 'assets/images/earth_bg.jpg',//地球贴图
imgEarth: 'http://10.19.151.238/earth_bg.jpg',//地球贴图
imgSky: 'assets/images/starry_sky_bg.jpg',//深空背景
autorotationSpeed: 0,//自转速度(正数自西向东转,负数为逆向)
cameraZ: 200,//摄像头高度,
earthBallSize: 30//地球大小
};
encEarth = new EncEarth("three-frame", earthOptions);
}