当前位置:   article > 正文

three.js 制作地球标注的两种方法_three-geo

three-geo

一,Sprite精灵标签

效果图:
在这里插入图片描述

//精灵标签--标签永远面向相机
function createTxt(position,name){					
	var texture = new THREE.CanvasTexture(getCanvasFont());
	var fontMesh = new THREE.Sprite(new THREE.SpriteMaterial({map: texture}));
	// 放大
	fontMesh.scale.x = 10;
	fontMesh.scale.y = 5;
	// 在原位置各加 2px ,避免文字与地标重叠
	fontMesh.position.x = (position.x >0 ? position.x+2 : position.x-2);
	fontMesh.position.y = (position.y >0 ? position.y+2 : position.y-2);
	fontMesh.position.z = (position.z >0 ? position.z+2 : position.z-2);
	// fontMesh.position.copy(position);	//原位置				
	scene.add(fontMesh);

	// canvas生成图片实现文字函数
	function getCanvasFont() {						
		let w = 600;
		let h = 300;
		let canvas = document.createElement("canvas");
		let ctx = canvas.getContext('2d');
		canvas.width = w;
		canvas.height = h;
		//制作矩形
		ctx.fillStyle = "red";
		ctx.fillRect(0, 0, w, h)
		//设置文字						
		ctx.fillStyle = "black";
		ctx.font = h/3 + 'px "微软雅黑"';						
		ctx.textAlign = 'center';
		ctx.fillText(name, w/2, h/2+20 )
		return canvas;
					}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

二,贴图标签

效果图:
在这里插入图片描述

//贴图标签,标签与球面融为一体
function createTextCanvas(position,name) {
	//用canvas生成图片
	let w = 200;
	let h = 100;
	let canvas = document.createElement("canvas");
	let ctx = canvas.getContext('2d');
	canvas.width = w;
	canvas.height = h;
	//左右翻转
	ctx.scale(-1, 1);
	ctx.translate(-w, 0);
	//制作矩形
	ctx.fillStyle = "red";
	ctx.fillRect(0, 0, w, h)
	//设置文字						
	ctx.fillStyle = "black";
	ctx.font = h/2 + 'px "微软雅黑"';
	ctx.textAlign = 'center';
	ctx.fillText(name, h, h/2+20);
	
	//生成图片
	let url = canvas.toDataURL('image/png');
	//几何体--长方形
	let geometry1 = new THREE.PlaneGeometry(6, 3);
	//将图片构建到纹理中
	let material1 = new THREE.MeshBasicMaterial({
		map: new THREE.TextureLoader().load(url),
		side: THREE.DoubleSide, //两面可见
		opacity: 1
	});
	let txtMesh = new THREE.Mesh(geometry1, material1);					
	txtMesh.position.copy(position);				
	txtMesh.lookAt(new THREE.Vector3(0, 0,0));					
	scene.add(txtMesh);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

三,完整代码

<!DOCTYPE html>
<html>
	<head>
		<title>Threejs实现绘制地球,地理位置标注</title>
		<meta charset="UTF-8">
		<script type="text/javascript" src="js/three.js"></script>
		<script type="text/javascript" src="js/OrbitControls.js"></script>
		<script type="text/javascript" src="js/makeTextSprite.js"></script>
		<style>
			body {
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<div id="dom"></div>
		<script type="text/javascript">
			var scene;
			var camera;
			var renderer;
			var radius = 100; // 地球半径
			var dom = document.getElementById("dom")
			var areas = [{
				name: "中国",
				position: [116.20, 39.55]
			}, {
				name: "中非共和国",
				position: [18.35, 4.23]
			}, {
				name: "智利",
				position: [-70.40, -33.24]
			}, {
				name: "乍得",
				position: [14.59, 12.10]
			}, {
				name: "赞比亚",
				position: [28.16, -15.28]
			}, {
				name: "越南",
				position: [105.55, 21.05]
			}, {
				name: "约旦",
				position: [35.52, 31.57]
			}, {
				name: "维尔京群岛",
				position: [-64.37, 18.27]
			}, {
				name: "英国",
				position: [-0.05, 51.36]
			}];


			function init() {
				// 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光。
				scene = new THREE.Scene();

				// 环境光(颜色,亮度)
				var ambientLight = new THREE.AmbientLight("#ffffff", 1.2);
				scene.add(ambientLight);

				// 创建一个摄像机,它定义了我们正在看的地方
				camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
				// 将摄像机对准场景的中心
				camera.position.set(0, 100, -400);
				camera.lookAt(scene.position);

				// 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景
				renderer = new THREE.WebGLRenderer({
					antialias: true, //是否执行抗锯齿
					logarithmicDepthBuffer: false, //如果要在单个场景中处理巨大的比例差异,就有必要使用。此处要用false,否则文字标签不显示
				});
				renderer.setSize(window.innerWidth, window.innerHeight);
				// renderer.setClearColor(0x000000, 1); //设置背景颜色

				// 设置背景图
				var texture = new THREE.TextureLoader().load('imges/back.jpg');
				scene.background = texture;

				// 显示坐标轴
				var axes = new THREE.AxisHelper(radius);
				scene.add(axes);

				//轨道控制器
				var controls = new THREE.OrbitControls(camera);
				controls.minPolarAngle = 0;
				controls.maxPolarAngle = Math.PI / 1; // 上下翻转范围 0-max度				
				controls.minDistance = 120; // 设置移动的最短距离(默认为零)
				controls.maxDistance = 1000; // 设置移动的最长距离(默认为无穷)				
				controls.update(); // 照相机转动时,必须更新该控制器	

				// 将呈现器的输出添加到HTML元素
				document.getElementById("dom").appendChild(renderer.domElement);

				// 运行函数
				createEarth();
				createAreaPoint();
				renderScene();

				// 创建地球 半径100
				function createEarth() {
					var earthGeo = new THREE.SphereGeometry(radius, 50, 50);
					var earthMater = new THREE.MeshPhongMaterial({
						map: new THREE.TextureLoader().load('imges/earth.jpg'),
						//透明球体
						// transparent: true,
						// depthWrite: false,
						// side: THREE.DoubleSide,
						// blending: THREE.AdditiveBlending,
						// opacity: 0.8,
						// color: 0x03d98e
					});
					var earthMesh = new THREE.Mesh(earthGeo, earthMater);
					scene.add(earthMesh);
				}
				
				// 创建地标
				function createAreaPoint() {
					// 循环创建地标,文字标签
					for (let i = 0, length = areas.length; i < length; i++) {
						const name = areas[i].name
						const position = createPosition(areas[i].position)
						createHexagon(position); // 地标函数
						createTxt(position,name); // 精灵标签函数
						// createTextCanvas(position,name) // 贴图标签函数
					}
				}

				// 经纬度转坐标
				function createPosition(lnglat) {
					let spherical = new THREE.Spherical
					spherical.radius = radius;
					const lng = lnglat[0]
					const lat = lnglat[1]
					const theta = (lng + 90) * (Math.PI / 180)
					const phi = (90 - lat) * (Math.PI / 180)
					spherical.phi = phi; // phi是方位面(水平面)内的角度,范围0~360度
					spherical.theta = theta; // theta是俯仰面(竖直面)内的角度,范围0~180度
					let position = new THREE.Vector3()
					position.setFromSpherical(spherical)
					return position
				}

				// 创建地标标记
				function createHexagon(position) {
					var hexagon = new THREE.Object3D()
					let hexagonLine = new THREE.CircleGeometry(2, 6)
					let hexagonPlane = new THREE.CircleGeometry(1, 6)
					let vertices = hexagonLine.vertices
					vertices.shift() // 第一个节点是中心点
					let material = new THREE.MeshBasicMaterial({
						color: 0xffff00,
						side: THREE.DoubleSide, //让材质单面或者双面显示,前面FrontSide ,背面:BackSide ,双面:DoubleSide
						opacity: 0.5
					})
					let circleLine = new THREE.LineLoop(hexagonLine, material)
					let circlePlane = new THREE.Mesh(hexagonPlane, material)
					circleLine.position.copy(position)
					circlePlane.position.copy(position)
					circlePlane.lookAt(new THREE.Vector3(0, 0, 0))
					circleLine.lookAt(new THREE.Vector3(0, 0, 0))

					hexagon.add(circleLine)
					hexagon.add(circlePlane)
					scene.add(hexagon);
				}

				//贴图标签,标签与球面融为一体
				function createTextCanvas(position,name) {
					//用canvas生成图片
					let w = 200;
					let h = 100;
					let canvas = document.createElement("canvas");
					let ctx = canvas.getContext('2d');
					canvas.width = w;
					canvas.height = h;
					//左右翻转
					ctx.scale(-1, 1);
					ctx.translate(-w, 0);
					//制作矩形
					ctx.fillStyle = "red";
					ctx.fillRect(0, 0, w, h)
					//设置文字						
					ctx.fillStyle = "black";
					ctx.font = h/2 + 'px "微软雅黑"';
					ctx.textAlign = 'center';
					ctx.fillText(name, h, h/2+20);
					
					//生成图片
					let url = canvas.toDataURL('image/png');
					//几何体--长方形
					let geometry1 = new THREE.PlaneGeometry(6, 3);
					//将图片构建到纹理中
					let material1 = new THREE.MeshBasicMaterial({
						map: new THREE.TextureLoader().load(url),
						side: THREE.DoubleSide, //两面可见
						opacity: 1
					});
					let txtMesh = new THREE.Mesh(geometry1, material1);					
					txtMesh.position.copy(position);				
					txtMesh.lookAt(new THREE.Vector3(0, 0,0));					
					scene.add(txtMesh);
				}
				
				//精灵标签--标签永远面向相机
				function createTxt(position,name){					
					var texture = new THREE.CanvasTexture(getCanvasFont());
					var fontMesh = new THREE.Sprite(new THREE.SpriteMaterial({map: texture}));
					// 放大
					fontMesh.scale.x = 10;
					fontMesh.scale.y = 5;
					// 在原位置各加 2px ,避免文字与地标重叠
					fontMesh.position.x = (position.x >0 ? position.x+2 : position.x-2);
					fontMesh.position.y = (position.y >0 ? position.y+2 : position.y-2);
					fontMesh.position.z = (position.z >0 ? position.z+2 : position.z-2);
					// fontMesh.position.copy(position);	//原位置				
					scene.add(fontMesh);

					// canvas生成图片实现文字函数
					function getCanvasFont() {						
						let w = 600;
						let h = 300;
						let canvas = document.createElement("canvas");
						let ctx = canvas.getContext('2d');
						canvas.width = w;
						canvas.height = h;
						//制作矩形
						ctx.fillStyle = "red";
						ctx.fillRect(0, 0, w, h)
						//设置文字						
						ctx.fillStyle = "black";
						ctx.font = h/3 + 'px "微软雅黑"';						
						ctx.textAlign = 'center';
						ctx.fillText(name, w/2, h/2+20 )
						return canvas;
					}
				}

				function renderScene() {
					requestAnimationFrame(renderScene); //循环调用renderScene函数
					renderer.render(scene, camera);
				}
			}

			// 随着窗体的变化修改场景大小
			function onResize() {
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth, window.innerHeight);
			}		

			// 监听窗体调整大小事件
			window.addEventListener('resize', onResize, false);

			/* 页面绘制完后加载,避免页面闪动 */
			window.onload = function() {
				init();
			}
			
		</script>
	</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263

参考文章:http://zuoben.top/#1-12
地球高清全景图: https://www.aliyundrive.com/s/C2kStb7B41c

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/95968
推荐阅读
相关标签
  

闽ICP备14008679号