three.js通过canvas实现球体世界平面地图
概况如下:
1、SphereGeometry实现自转的地球;
2、THREE.CatmullRomCurve3实现球体线条地图点确定;
3、THREE.Math.degToRad,Math.sin,Math.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实现球体世界平面地图的更多相关文章
- three.js实现世界3d地图
概况如下: 1.THREE.Shape绘制世界地图平面地图: 2.THREE.ExtrudeGeometry将绘制的平面沿着Z轴拉伸,实现3d效果: 效果图如下: 预览地址:three.js实现世界3 ...
- Three.js - 走进3D的奇妙世界
本文将通过Three.js的介绍及示例带我们走进3D的奇妙世界. 文章来源:宜信技术学院 & 宜信支付结算团队技术分享第6期-支付结算部支付研发团队前端研发高级工程师-刘琳<three. ...
- Particles.js基于Canvas画布创建粒子原子颗粒效果
文章目录 使用方法 自定义参数 相关链接 Particles.js是一款基于HTML5 Canvas画布的轻量级粒子动画插件,可以设置粒子的形状.旋转.分布.颜色等属性,还可以动态添加粒子,效果非常炫 ...
- 原生js实现canvas气泡冒泡效果
说明: 本文章主要分为ES5和ES6两个版本 ES5版本是早期版本,后面用ES6重写优化的,建议使用ES6版本. 1, 原生js实现canvas气泡冒泡效果的插件,api丰富,使用简单2, 只需引入J ...
- captcha.js一个生成验证码的插件,使用js和canvas生成
一.captcha`captcha.js`是一个生成验证码的插件,使用js和canvas生成的,确保后端服务被暴力攻击,简单判断人机以及系统的安全性,体积小,功能多,支持配置. 验证码插件内容,包含1 ...
- Qt的QWebChannel和JS、HTML通信/交互驱动百度地图
Qt的QWebChannel和JS.HTML通信/交互驱动百度地图 0 前言 我一个研究嵌入式的,不知道怎么就迷上了上位机,接了几个项目都是关于Qt,这个项目还是比较经典的,自己没事儿的时候也进行研究 ...
- Python 绘制2016世界GDP地图
2016世界GDP地图 从https://datahub.io/core/gdp#data下载得到json文件. # country_code.py 获取国家二字代码 # 从pygal.maps.wo ...
- Three.js基础探寻四——立方体、平面与球体
前面简单介绍了webGL和Three.js的背景以及照相机的设定,接下来介绍一些Three.js中的几何形状. 1.立方体 虽然这一形状的名字叫立方体(CubeGeometry),但它其实是长方体,也 ...
- three.js学习:纹理Texture之平面纹理
index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
随机推荐
- 使用react-app-rewired和customize-cra对默认webpack自定义配置
最近在学习react框架,之前一直都是用vue 开发,知道在vue 中知道如何配置一下相关的webpack 有助于开发,学react 过程中,我也在想这些该怎么配置啊,所以就有这篇文章. 这篇文章主要 ...
- [Android逆向]APK反编译与回编译
一.先查壳,再反编译看验证首先打开.apk文件==>反编译apk(dex/配置文件/资源文件(apk反编译失败)>修改关键文件实现自己的目的>重新打包签名(无法重新打包)==> ...
- CentOS 7上的主机名设置和基本网络管理
主机名 CentOS 6 查看. # hostname 设置. # hostname NEW_NAME 设置完成后,xshell的会话中不会显示NEW_NAME,可通过重新登录会话来显示.不过实际上我 ...
- 关于List和String有意思的几个应用
关于List和String有意思的几个应用 1. List:all_equal 功能:验证列表中的所有元素是否是都一样的. 解析:该技巧是使用[1:] 和 [:-1] 来比较所给定列表中的所有元素 ...
- Spring Boot启动提示:org.apache.catalina.LifecycleException: A child container failed during start
一.问题回顾 最近在做一个新项目,从git上下载导入idea后,启动项目,但是报了如下错误: java.util.concurrent.ExecutionException: org.apache.c ...
- Nginx:The Location Block Selection Algorithm
Nginx:The Location Block Selection Algorithm,摘自NGINX:A PRACTICAL GUIDE TO HIGH PERFORMANCE Nginx配置文件 ...
- vue路由进阶
一..全局路由前置守卫 1.首先看一下文档结构 Dashboard和Login是一级页面 home about mine是在Dashboard下的二级页面 2.router.js代码如下 impor ...
- 东芝开发板驱动OLED模块显示LOGO图片
前言 在之前的两篇评测文章: 使用系统定时器SysTick实现精确延时微秒和毫秒函数 东芝MCU实现位带操作 介绍了系统SysTick实现精确延时,GPIO的输入输出使用,并实现了位带方式操作GPIO ...
- P1356 数列的整除性
dp百题进度条[2/100] 题目链接 题目描述 对于任意一个整数数列,我们可以在每两个整数中间任意放一个符号'+'或'-',这样就可以构成一个表达式,也就可以计算出表达式的值.比如,现在有一个整数数 ...
- Filter List Views 筛选器列表视图
In this lesson, you will learn how to filter a List View. Three techniques, based on different scena ...