概况如下:
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. C#学习书单

    [入门] (1)<C#入门经典> (2)<牛腩新闻发布系统> [深入] (1)<CLR via C#(第4版)> (2)<深入理解C#(第3版)> [C ...

  2. python基础——字典(dict)

    字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 . dict1 = {} ...

  3. element 上传组件 el-upload 的经验总结

    前言 最近在做后台管理项目,采用的 vue-element-admin ,上传图片是一个很常用的功能,也遇到了很多问题,刚好趁此机会做一些总结. 初步总结下会提到的问题,目录如下: el-upload ...

  4. thymeleaf介绍

    作者:纯洁的微笑出处:http://www.ityouknow.com/  增加了一小部分内容 简单说, Thymeleaf 是一个跟 Velocity.FreeMarker 类似的模板引擎,它可以完 ...

  5. PageHelper分页实战(SSM整合)

    步骤一:引入SSM相关的jar包,包列表如下: 步骤二:创建或修改配置文件,配置文件清单如下: applicationContext.xml <?xml version="1.0&qu ...

  6. JS面向对象编程(一):封装

    js是一门基于面向对象编程的语言.      如果我们要把(属性)和(方法)封装成一个对象,甚至要从原型对象生成一个实例,我们应该怎么做呢?  一.生成对象的原始模式            假定把猫看 ...

  7. java抽奖思路

    现在在做一个有关抽奖的活动,将我自己所做的抽奖思路书写一下 1.项目奖项的配置存储在MongoDB 配置的参数为 奖项的等级(prizeLevel).数量(prizeNum).奖项的名称(prizeN ...

  8. 【iOS】安装 CocoaPods

    1. 打开 terminal 2. 移除现有 Ruby 默认源 $ gem sources --remove https://rubygems.org/ 3. 使用新的源 $ gem sources ...

  9. 关于定时器Scheduled(cron)的问题

    定时器配置步骤参考:http://blog.csdn.NET/sd4000784/article/details/7745947 下面给出cron参数中各个参数的含义: CRON表达式    含义 & ...

  10. Confluence未授权模板注入/代码执行(CVE-2019-3396)

    --- title: Confluence未授权模板注入/代码执行(CVE-2019-3396) tags: [poc,cve] num :g7y12 --- # 简介 --- Confluence是 ...