概况如下:
1、SphereGeometry实现自转的地球;
2、THREE.ImageUtils.loadTexture加载地图贴图材质;
3、THREE.Math.degToRad,Math.sin,Math.cos实现地图经纬度与三位坐标x,y,z之间的转换;
4、轨迹中根据分段数与相应国家gdp值来实现城市标记。

效果图如下:

预览地址:three.js实现球体地球城市模拟迁徙

初始化场景、相机、渲染器,设置相机位置,初始化光源,光源采用HemisphereLight,设置光源位置为场景中心位置,并将光源加入场景中

// 初始化场景
var scene = new THREE.Scene();
// 初始化相机,第一个参数为摄像机视锥体垂直视野角度,第二个参数为摄像机视锥体长宽比,
// 第三个参数为摄像机视锥体近端面,第四个参数为摄像机视锥体远端面
var camera = new THREE.PerspectiveCamera(20, dom.clientWidth / dom.clientHeight, 1, 100000);
// 设置相机位置,对应参数分别表示x,y,z位置
camera.position.set(0, 0, 200);
var renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
// 设置光照
scene.add(new THREE.HemisphereLight('#ffffff', '#ffffff', 1));

设置场景窗口尺寸,并且初始化控制器,窗口尺寸默认与浏览器窗口尺寸保持一致,最后将渲染器加载到dom中。

// 设置窗口尺寸,第一个参数为宽度,第二个参数为高度
renderer.setSize(dom.clientWidth, dom.clientHeight);
// 初始化控制器
var orbitcontrols = new THREE.OrbitControls(camera,renderer.domElement);
// 将渲染器加载到dom中
dom.appendChild(renderer.domElement);

定义地球及其材质,地球通过SphereGeometry来实现,通过ImageUtils来导入贴图。

// 定义地球材质
var earthTexture = THREE.ImageUtils.loadTexture(earthImg, {}, function () {
renderer.render(scene, camera);
});
// 创建地球
earthBall = new THREE.Mesh(new THREE.SphereGeometry(earthBallSize, 50, 50), new THREE.MeshBasicMaterial({
map: earthTexture
}));
scene.add(earthBall);

标记地点经纬度坐标与三维x,y,z坐标转换方法。

// 经纬度转换函数,longitude表示经度,latitude表示唯独,radius表示球体半径
var getPosition = function (longitude, latitude, radius) {
// 将经度,纬度转换为rad坐标
var lg = THREE.Math.degToRad(longitude);
var lt = THREE.Math.degToRad(latitude);
var temp = radius * Math.cos(lt);
// 获取x,y,z坐标
var x = temp * Math.sin(lg);
var y = radius * Math.sin(lt);
var z = temp * Math.cos(lg);
return {
x: x,
y: y,
z: z
}
}

添加两个城市之间轨迹的方法。

// 添加轨迹函数
var addLine = function (v0, v3) {
var angle = (v0.angleTo(v3) * 180) / Math.PI;
var aLen = angle * 0.5 * (1 - angle / (Math.PI * earthBallSize * parseInt(earthBallSize / 10)));
var hLen = angle * angle * 1.2 * (1 - angle / (Math.PI * earthBallSize * parseInt(earthBallSize / 10)));
var p0 = new THREE.Vector3(0, 0, 0);
// 法线向量
var rayLine = new THREE.Ray(p0, getVCenter(v0.clone(), v3.clone()));
// 顶点坐标
var vtop = rayLine.at(hLen / rayLine.at(1).distanceTo(p0));
// 控制点坐标
var v1 = getLenVcetor(v0.clone(), vtop, aLen);
var v2 = getLenVcetor(v3.clone(), vtop, aLen);
// 绘制贝塞尔曲线
var curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);
var geometry = new THREE.Geometry();
geometry.vertices = curve.getPoints(100);
var line = new MeshLine();
line.setGeometry(geometry);
var material = new MeshLineMaterial({
color: metapLineColor,
lineWidth: 0.1,
transparent: true,
opacity: 1
})
return {
curve: curve,
lineMesh: new THREE.Mesh(line.geometry, material)
}
}

轨迹上运动的小球实现方法。

var animateDots = [];
// 线条对象集合
var groupLines = new THREE.Group();
// 线条
marking.children.forEach(function (item) {
var line = addLine(marking.children[0].position, item.position);
groupLines.add(line.lineMesh);
animateDots.push(line.curve.getPoints(metapNum));
})
scene.add(groupLines);
// 线上滑动的小球
var aGroup = new THREE.Group();
for (var i = 0; i < animateDots.length; i ++) {
for (var j = 0; j < markingNum; j ++) {
var aGeo = new THREE.SphereGeometry(slideBallSize, 10, 10);
var aMaterial = new THREE.MeshBasicMaterial({
color: slideBallColor,
transparent: true,
opacity: 1 - j * 0.02
})
var aMesh = new THREE.Mesh(aGeo, aMaterial);
aGroup.add(aMesh);
}
}
var vIndex = 0;
var firstBool = true;
function animationLine () {
aGroup.children.forEach(function (elem, index) {
var _index = parseInt(index / markingNum);
var index2 = index - markingNum * _index;
var _vIndex = 0;
if (firstBool) {
_vIndex = vIndex - index2 % markingNum >= 0 ? vIndex - index2 % markingNum : 0;
} else {
_vIndex = vIndex - index2 % markingNum >= 0 ? vIndex - index2 % markingNum : metapNum + vIndex - index2;
}
var v = animateDots[_index][_vIndex];
elem.position.set(v.x, v.y, v.z);
})
vIndex ++;
if (vIndex > metapNum) {
vIndex = 0;
}
if (vIndex == metapNum && firstBool) {
firstBool = false;
}
requestAnimationFrame(animationLine);
}
scene.add(aGroup);

标记地点通过position值来实现位置的确认,动画使用requestAnimationFrame来实现。

// 执行函数
var render = function () {
scene.rotation.y -= 0.01;
renderer.render(scene, camera);
orbitcontrols.update();
requestAnimationFrame(render);
}

three.js实现球体地球城市模拟迁徙的更多相关文章

  1. three.js实现球体地球2018年全球GDP前十国家标记

    概况如下: 1.SphereGeometry实现自转的地球: 2.THREE.Math.degToRad,Math.sin,Math.cos实现地图经纬度与三位坐标x,y,z之间的转换: 3.Imag ...

  2. vue中使用 echarts3.0 或 echarts2.0 (模拟迁徙图,折线图)

    一.echarts3.0(官网: http://echarts.baidu.com/) 首先通过npm安装echarts依赖,安装的为3.0版本 npm install echarts -s 也可以使 ...

  3. ECharts模拟迁徙案例

    ECharts模拟迁徙案例 独立页面:http://211.140.7.173:8081/t/wuhairui/ditu/a.html

  4. JS前端三维地球渲染——中国各城市航空路线展示

    前言 我还从来没有写过有关纯JS的文章(上次的矢量瓦片展示除外,相对较简单.),自己也学习过JS.CSS等前端知识,了解JQuery.React等框架,但是自己艺术天分实在不过关,不太喜欢前端设计,比 ...

  5. arcgis api 4.x for js 集成 Echarts4 实现模拟迁徙图效果(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 4.x for js:esri 官网 api,里面详细的介绍 arcgis api 4.x 各个类 ...

  6. JS+HTML5的Canvas画图模拟太阳系运转

    查看效果:http://hovertree.com/texiao/html5/9.htm 地球自传 http://hovertree.com/texiao/html5/8.htm 代码如下: < ...

  7. arcgis api for js入门开发系列十六迁徙流动图

    最近公司有个arcgis api for js的项目,需要用到百度echarts迁徙图效果,而百度那个效果实现是结合百度地图的,怎么才能跟arcgis api结合呢,网上搜索,终于在github找到了 ...

  8. arcgis api 3.x for js 入门开发系列十六迁徙流动图

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  9. JS根据登录的城市不同调用不同的内容

    这个思路就是通过js获取访问客户的IP地址,根据IP接口判断IP的所属城市 1.先引入ip接口的js文件,网上有很多,这里用的是新浪的(感谢新浪) <script type="text ...

随机推荐

  1. WSASocket()创建套接字不成功解决方法

    这几天我在写一个模仿windows自带的ping程序,可是套接字总是创建不成功,在网上找了一些资料最后总算把问题解决了,现在总结一下. 解决方法:以管理员运行VS就行了我的是vs2013,vs2010 ...

  2. k8s1.9.0安装--环境准备

    一.预先准备环境 1. 准备服务器 这里准备了三台centos虚拟机,每台一核cpu和2G内存,配置好root账户,并安装好了docker,后续的所有操作都是使用root账户.虚拟机具体信息如下表: ...

  3. js - 使用jquery发送前台请求给服务器,并显示数据

    1.使用jquery发送前台请求给服务器,并显示数据 <%@ page contentType="text/html;charset=UTF-8" language=&quo ...

  4. Shell基本语法---shell介绍

    简介 1. shell是在linux系统上高效运行的脚本语言 2. 主要用来开发一些实用的.自动化的小工具,而不是用来开发具有复杂业务逻辑的中大型软件 3. shell的基本命令也是linux操作系统 ...

  5. 19.包 logging 的使用

    包 什么是包: ---文件夹下具有__init__.py文件就是一个包 推荐使用 from . import 包的导入; from ss.bake.api.policy import func --- ...

  6. Linux内核实战(二)- 操作系统概览

    不知道你有没有产生过这些疑问: 桌面上的图标到底是啥?凭啥我在鼠标上一双击,就会出来一些不可描述的画面?都是从哪里跑出来的? 凭什么我在键盘上噼里啪啦地敲,某个位置就会显示我想要的那些字符? 电脑怎么 ...

  7. 从无到满意offer,你需要知道的那些事

    本文首发于微信公众号:[坂本先生] 原文地址:从无到满意offer,你需要知道的那些事 1.求职软件/网站汇总 软件 评价 推荐指数 拉钩网 手机端产品设计的比较好,当时在上面找到了很多的面试机会 5 ...

  8. c#将字符串转化为合理的文件名

    string name = System.Text.RegularExpressions.Regex.Replace(url, "[<>/\\|:\"?*]" ...

  9. js中判断一个对象的类型的种种方法

    javascript中检测对象的类型的运算符有:typeof.constructor.instanceof. typeof:typeof是一个一元运算符,返回结果是一个说明运算数类型的字符串.如:&q ...

  10. pythonday04数据类型(二)

    今日内容: 1.列表 2.元组 3.py2与py3的区别 4解释器/编译器 5.练习题 1.列表 想要表示多个”事物“,可以使用列表 users = ["李邵奇","奇航 ...