概况如下:

1、SphereGeometry实现自转的地球;

2、THREE.CatmullRomCurve3实现球体线条地图点确定;

3、THREE.Math.degToRadMath.sinMath.cos实现地图经纬度与三位坐标x,y,z之间的转换;

4、MeshLine用于绘制线条;

5、canvas用于绘制球体世界地图贴图,通过THREE.CanvasTexture引入。

效果图如下:

预览地址:three.js通过canvas实现球体世界平面地图

初始化场景、相机、渲染器,设置相机位置,初始化光源,光源采用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);

通过canvas定义地球材质。

 // canvas画地图函数,因为性能问题,线条不再canvas中实现,w表示宽度,h表示高度,worldPos表示世界地图经纬度信息
var createCanvas = function (w, h, worldPos) {
var canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
var context = canvas.getContext('2d');
var centerX = w / 2;
var centerY = h / 2;
var average = w / 360;
// 绘制背景颜色
context.fillStyle = earthBallColor;
context.fillRect(0, 0, w, h);
// canvas中绘制地图方法
function canvasLineFun (childrenPosition) {
context.fillStyle = earthBallPlaneColor;
context.moveTo(centerX + childrenPosition[0][0] * average, centerY - childrenPosition[0][1] * average);
childrenPosition.forEach(function (posItem) {
context.lineTo(centerX + posItem[0] * average, centerY - posItem[1] * average);
})
context.closePath();
context.fill();
}
worldPos.forEach(function (item) {
canvasLineFun(item);
})
return canvas;
}

定义地球及其材质,地球通过SphereGeometry来实现,通过THREE.CanvasTexture来引入canvas创建的贴图。

 // 创建地球
earthBall = new THREE.Mesh(new THREE.SphereGeometry(earthBallSize, 50, 50), new THREE.MeshBasicMaterial({
map: new THREE.CanvasTexture(createCanvas(2048, 1024, worldGeometry)),
side: THREE.FrontSide
}));
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 drawWorldLine = function (pos, identify) {
var posArray = [];
pos.forEach(function (item) {
var pointPosition = getPosition(item[0] + 90, item[1], earthBallSize);
posArray.push(new THREE.Vector3(pointPosition.x, pointPosition.y, pointPosition.z));
})
// 绘制的线条需要关闭,第二个参数默认为false,表示不关闭
var curve = new THREE.CatmullRomCurve3(posArray, true);
var points = curve.getPoints(500);
var geometry = new THREE.Geometry().setFromPoints(points);
// 定义线条
var line = new MeshLine();
line.setGeometry(geometry);
// 定义线条材质
var material = new MeshLineMaterial({
color: worldLineColor,
lineWidth: worldLineWidth
})
// 绘制地图
lineGeometryObj['lineGeometry' + identify] = new THREE.Mesh(line.geometry, material);
// 将地图加入场景
scene.add(lineGeometryObj['lineGeometry' + identify])
}

获取世界地图经纬度信息及计算绘制球体地图参数方法

 // 获取世界经纬度信息函数
var getWorldGeometry = function () {
$.ajax({
type : "GET", //提交方式
url : "./code/world.json",
async: false,
success : function(response) {//返回数据根据结果进行相应的处理
worldGeometry = [];
// 绘制世界地图
response.features.forEach(function (worldItem, worldItemIndex) {
var length = worldItem.geometry.coordinates.length;
var multipleBool = length > 1 ? true : false;
worldItem.geometry.coordinates.forEach(function (worldChildItem, worldChildItemIndex) {
if (multipleBool) {
// 值界可以使用的经纬度信息
if (worldChildItem.length && worldChildItem[0].length == 2) {
worldGeometry.push(worldChildItem);
}
// 需要转换才可以使用的经纬度信息
if (worldChildItem.length && worldChildItem[0].length > 2) {
worldChildItem.forEach(function (countryItem, countryItenIndex) {
worldGeometry.push(countryItem);
})
}
} else {
var countryPos = null;
if (worldChildItem.length > 1) {
countryPos = worldChildItem;
} else {
countryPos = worldChildItem[0];
}
if (countryPos) {
worldGeometry.push(countryPos);
}
}
})
})
}
})
}

球体地图线条通过position值来实现位置的确认,动画使用requestAnimationFrame来实现。

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

three.js通过canvas实现球体世界平面地图的更多相关文章

  1. three.js实现世界3d地图

    概况如下: 1.THREE.Shape绘制世界地图平面地图: 2.THREE.ExtrudeGeometry将绘制的平面沿着Z轴拉伸,实现3d效果: 效果图如下: 预览地址:three.js实现世界3 ...

  2. Three.js - 走进3D的奇妙世界

    本文将通过Three.js的介绍及示例带我们走进3D的奇妙世界. 文章来源:宜信技术学院 & 宜信支付结算团队技术分享第6期-支付结算部支付研发团队前端研发高级工程师-刘琳<three. ...

  3. Particles.js基于Canvas画布创建粒子原子颗粒效果

    文章目录 使用方法 自定义参数 相关链接 Particles.js是一款基于HTML5 Canvas画布的轻量级粒子动画插件,可以设置粒子的形状.旋转.分布.颜色等属性,还可以动态添加粒子,效果非常炫 ...

  4. 原生js实现canvas气泡冒泡效果

    说明: 本文章主要分为ES5和ES6两个版本 ES5版本是早期版本,后面用ES6重写优化的,建议使用ES6版本. 1, 原生js实现canvas气泡冒泡效果的插件,api丰富,使用简单2, 只需引入J ...

  5. captcha.js一个生成验证码的插件,使用js和canvas生成

    一.captcha`captcha.js`是一个生成验证码的插件,使用js和canvas生成的,确保后端服务被暴力攻击,简单判断人机以及系统的安全性,体积小,功能多,支持配置. 验证码插件内容,包含1 ...

  6. Qt的QWebChannel和JS、HTML通信/交互驱动百度地图

    Qt的QWebChannel和JS.HTML通信/交互驱动百度地图 0 前言 我一个研究嵌入式的,不知道怎么就迷上了上位机,接了几个项目都是关于Qt,这个项目还是比较经典的,自己没事儿的时候也进行研究 ...

  7. Python 绘制2016世界GDP地图

    2016世界GDP地图 从https://datahub.io/core/gdp#data下载得到json文件. # country_code.py 获取国家二字代码 # 从pygal.maps.wo ...

  8. Three.js基础探寻四——立方体、平面与球体

    前面简单介绍了webGL和Three.js的背景以及照相机的设定,接下来介绍一些Three.js中的几何形状. 1.立方体 虽然这一形状的名字叫立方体(CubeGeometry),但它其实是长方体,也 ...

  9. three.js学习:纹理Texture之平面纹理

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

随机推荐

  1. Atmel Studio 7.0 的使用方法

    就在最近,Atmel终于推出了新版本IDE——Atmel Studio 7.0,该版本采用了微软最新的 Visual Studio 2015 平台,经过一段时间使用,Atmel Studio 7.0在 ...

  2. python多线程编程—同步原语入门(锁Lock、信号量(Bounded)Semaphore)

    摘录python核心编程 一般的,多线程代码中,总有一些特定的函数或者代码块不希望(或不应该)被多个线程同时执行(比如两个线程运行的顺序发生变化,就可能造成代码的执行轨迹或者行为不相同,或者产生不一致 ...

  3. 我也开源... React Native Messager

    近期有空,玩转React Native. https://github.com/andyc365/ReactNativeMessager React Native Messager A React N ...

  4. scrapy框架(三)

    scrapy框架(三) CrawlSpider类 创建CrawlSpider  # 创建项目后 $ scrapy genspider -t crawl spider_name website_doma ...

  5. .NET Core 3.0正式版发布

    是的,.NET Core 3.0正式版发布了,令人兴奋. WPF 其实,.NET Core 2.1开始已经是个很完善的版本,3.0又带来了什么呢?我站在我的使用角度来看,最最令人振奋的就是:能用WPF ...

  6. Linux selinux 规则导致audit拒绝

    Linux selinux 规则导致audit拒绝 转载注明来源: 本文链接 来自osnosn的博客,写于 2019-09-26. 查看 audit2why -d audit2allow 这两个命令. ...

  7. IT兄弟连 HTML5教程 W3C盒子模型

    日常生活中所见的盒子也就是能装东西的一种箱子,如果家里的东西很多,那么就需要按类别装到不同的箱子中.网页中的内容表现也是一样的,如果页面内容比较多,又想让页面更整洁.更美观.有很好的用户体验,则也需要 ...

  8. UWP 在ShellPage.xaml.cs 中导航至其他页面引发System.Exception

    最近有一个需求,需要App监测网络变化,并在网络变化的同时用户,你切网啦,并且导航至一个切网的特定页面. 和Android.iOS的小伙伴后共同发现,人家有一个类似”拦截器“的框架,可以拦截App发出 ...

  9. Mysql - 高可用方案之MM+Keepalived

    一.概述 本文将介绍mysql的MM+Keepalived方案.该方案由两个mysql服务器组成,这两个mysql互为主备.其中一台主作为写服务器,另一台主作为读服务器.通过keepalived软件管 ...

  10. Java学习 1.1——(JVM介绍)Java为什么能够跨平台?

    首先介绍一下Java的各个层级,先放一张图: 硬件,操作系统和操作系统接口:这三级不说大家都知道,操作系统有很多种,比如Windows,Linux.Windows又分为win7,win10,win x ...