three.js通过canvas实现球体世界平面地图
概況如下:
1、SphereGeometry實現(xiàn)自轉的地球;
2、THREE.CatmullRomCurve3實現(xiàn)球體線條地圖點確定;
3、THREE.Math.degToRad,Math.sin,Math.cos實現(xiàn)地圖經(jīng)緯度與三位坐標x,y,z之間的轉換;
4、MeshLine用于繪制線條;
5、canvas用于繪制球體世界地圖貼圖,通過THREE.CanvasTexture引入。
效果圖如下:
預覽地址:three.js通過canvas實現(xiàn)球體世界平面地圖
初始化場景、相機、渲染器,設置相機位置,初始化光源,光源采用HemisphereLight,設置光源位置為場景中心位置,并將光源加入場景中。
1 // 初始化場景
2 var scene = new THREE.Scene();
3 // 初始化相機,第一個參數(shù)為攝像機視錐體垂直視野角度,第二個參數(shù)為攝像機視錐體長寬比,
4 // 第三個參數(shù)為攝像機視錐體近端面,第四個參數(shù)為攝像機視錐體遠端面
5 var camera = new THREE.PerspectiveCamera(20, dom.clientWidth / dom.clientHeight, 1, 100000);
6 // 設置相機位置,對應參數(shù)分別表示x,y,z位置
7 camera.position.set(0, 0, 200);
8 var renderer = new THREE.WebGLRenderer({
9 alpha: true,
10 antialias: true
11 });
12 // 設置光照
13 scene.add(new THREE.HemisphereLight('#ffffff', '#ffffff', 1));
設置場景窗口尺寸,并且初始化控制器,窗口尺寸默認與瀏覽器窗口尺寸保持一致,最后將渲染器加載到dom中。
1 // 設置窗口尺寸,第一個參數(shù)為寬度,第二個參數(shù)為高度 2 renderer.setSize(dom.clientWidth, dom.clientHeight); 3 // 初始化控制器 4 var orbitcontrols = new THREE.OrbitControls(camera,renderer.domElement); 5 // 將渲染器加載到dom中 6 dom.appendChild(renderer.domElement);
通過canvas定義地球材質(zhì)。
1 // canvas畫地圖函數(shù),因為性能問題,線條不再canvas中實現(xiàn),w表示寬度,h表示高度,worldPos表示世界地圖經(jīng)緯度信息
2 var createCanvas = function (w, h, worldPos) {
3 var canvas = document.createElement('canvas');
4 canvas.width = w;
5 canvas.height = h;
6 var context = canvas.getContext('2d');
7 var centerX = w / 2;
8 var centerY = h / 2;
9 var average = w / 360;
10 // 繪制背景顏色
11 context.fillStyle = earthBallColor;
12 context.fillRect(0, 0, w, h);
13 // canvas中繪制地圖方法
14 function canvasLineFun (childrenPosition) {
15 context.fillStyle = earthBallPlaneColor;
16 context.moveTo(centerX + childrenPosition[0][0] * average, centerY - childrenPosition[0][1] * average);
17 childrenPosition.forEach(function (posItem) {
18 context.lineTo(centerX + posItem[0] * average, centerY - posItem[1] * average);
19 })
20 context.closePath();
21 context.fill();
22 }
23 worldPos.forEach(function (item) {
24 canvasLineFun(item);
25 })
26 return canvas;
27 }
定義地球及其材質(zhì),地球通過SphereGeometry來實現(xiàn),通過THREE.CanvasTexture來引入canvas創(chuàng)建的貼圖。
1 // 創(chuàng)建地球
2 earthBall = new THREE.Mesh(new THREE.SphereGeometry(earthBallSize, 50, 50), new THREE.MeshBasicMaterial({
3 map: new THREE.CanvasTexture(createCanvas(2048, 1024, worldGeometry)),
4 side: THREE.FrontSide
5 }));
6 scene.add(earthBall);
標記地點經(jīng)緯度坐標與三維x,y,z坐標轉換方法。
1 // 經(jīng)緯度轉換函數(shù),longitude表示經(jīng)度,latitude表示唯獨,radius表示球體半徑
2 var getPosition = function (longitude, latitude, radius) {
3 // 將經(jīng)度,緯度轉換為rad坐標
4 var lg = THREE.Math.degToRad(longitude);
5 var lt = THREE.Math.degToRad(latitude);
6 var temp = radius * Math.cos(lt);
7 // 獲取x,y,z坐標
8 var x = temp * Math.sin(lg);
9 var y = radius * Math.sin(lt);
10 var z = temp * Math.cos(lg);
11 return {
12 x: x,
13 y: y,
14 z: z
15 }
16 }
繪制世界地圖線條方法
1 // 繪制世界地圖線條函數(shù)
2 var drawWorldLine = function (pos, identify) {
3 var posArray = [];
4 pos.forEach(function (item) {
5 var pointPosition = getPosition(item[0] + 90, item[1], earthBallSize);
6 posArray.push(new THREE.Vector3(pointPosition.x, pointPosition.y, pointPosition.z));
7 })
8 // 繪制的線條需要關閉,第二個參數(shù)默認為false,表示不關閉
9 var curve = new THREE.CatmullRomCurve3(posArray, true);
10 var points = curve.getPoints(500);
11 var geometry = new THREE.Geometry().setFromPoints(points);
12 // 定義線條
13 var line = new MeshLine();
14 line.setGeometry(geometry);
15 // 定義線條材質(zhì)
16 var material = new MeshLineMaterial({
17 color: worldLineColor,
18 lineWidth: worldLineWidth
19 })
20 // 繪制地圖
21 lineGeometryObj['lineGeometry' + identify] = new THREE.Mesh(line.geometry, material);
22 // 將地圖加入場景
23 scene.add(lineGeometryObj['lineGeometry' + identify])
24 }
獲取世界地圖經(jīng)緯度信息及計算繪制球體地圖參數(shù)方法
1 // 獲取世界經(jīng)緯度信息函數(shù)
2 var getWorldGeometry = function () {
3 $.ajax({
4 type : "GET", //提交方式
5 url : "./code/world.json",
6 async: false,
7 success : function(response) {//返回數(shù)據(jù)根據(jù)結果進行相應的處理
8 worldGeometry = [];
9 // 繪制世界地圖
10 response.features.forEach(function (worldItem, worldItemIndex) {
11 var length = worldItem.geometry.coordinates.length;
12 var multipleBool = length > 1 ? true : false;
13 worldItem.geometry.coordinates.forEach(function (worldChildItem, worldChildItemIndex) {
14 if (multipleBool) {
15 // 值界可以使用的經(jīng)緯度信息
16 if (worldChildItem.length && worldChildItem[0].length == 2) {
17 worldGeometry.push(worldChildItem);
18 }
19 // 需要轉換才可以使用的經(jīng)緯度信息
20 if (worldChildItem.length && worldChildItem[0].length > 2) {
21 worldChildItem.forEach(function (countryItem, countryItenIndex) {
22 worldGeometry.push(countryItem);
23 })
24 }
25 } else {
26 var countryPos = null;
27 if (worldChildItem.length > 1) {
28 countryPos = worldChildItem;
29 } else {
30 countryPos = worldChildItem[0];
31 }
32 if (countryPos) {
33 worldGeometry.push(countryPos);
34 }
35 }
36 })
37 })
38 }
39 })
40 }
球體地圖線條通過position值來實現(xiàn)位置的確認,動畫使用requestAnimationFrame來實現(xiàn)。
1 // 執(zhí)行函數(shù)
2 var render = function () {
3 scene.rotation.y -= 0.01;
4 renderer.render(scene, camera);
5 orbitcontrols.update();
6 requestAnimationFrame(render);
7 }
總結
以上是生活随笔為你收集整理的three.js通过canvas实现球体世界平面地图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序之授权 wx.authoriz
- 下一篇: centos7全新系统安装TensorF