Notas varias de Three.js (11) -Elfos y partículas (dibujar un mapa de China)

Introducción a Sprite

El objeto modelo Sprite Sprite . El objeto del modelo de sprite y el modelo de malla necesitan configurar el material, pero el modelo de sprite no necesita que el programador configure la geometría, se configurará automáticamente cuando el sistema Threejs se renderice.

A través del modelo de sprite de Threejs, puede establecer etiquetas para los objetos del modelo en la escena y también puede generar una gran cantidad de objetos del modelo de sprite para simular un sistema de partículas.

El objeto Sprite del modelo de sprite de three.js es el mismo que el modelo de malla de Threejs Mesh. La clase base es Object3D. Para los métodos y propiedades del objeto Sprite del modelo de sprite, puedes ver el documento Sprite así como la clase base Object3D.

La creación de un objeto de modelo de sprite requiere la creación de un objeto de material al igual que la creación de un objeto de modelo de malla. La diferencia es que para crear un objeto de modelo de sprite no es necesario crear un objeto de geometría Geometría. En esencia, puedes entender que un modelo de sprite El objeto ha encapsulado una geometría rectangular plana en el interior PlaneGeometry, la diferencia entre el modelo de sprite rectangular y el modelo de cuadrícula rectangular es que el plano rectangular del modelo de sprite siempre será paralelo al lienzo Canvas .

Si desea comprender la esencia del modelo de sprite, puede leer el archivo oficial three.js-master el código fuente del paquete del objeto del modelo de sprite \src\objects\Sprite.jsy analizar el código fuente del modelo de sprite \src\renderers\webgl\WebGLSpriteRenderer.js.

Sprite 和 SpriteMaterial

Para crear un modelo de sprite a través de Sprite, no se requiere geometría, solo necesita establecer el parámetro del constructor Sprite en un material de sprite SpriteMaterial .

El objeto de material de sprite SpriteMaterial puede establecer el color.color, colormap.map, transparencia abierta.transparente, transparencia.opacidad y otras propiedades como materiales de malla ordinarios. La clase base del objeto de material de sprite SpriteMaterial es el material Material .

Usos de Sprite

Hablando del objeto del modelo de sprite, en este caso debes preocuparte por su propósito. En cuanto al propósito, puedes usar el modelo de sprite como una etiqueta de modelo en la escena 3D. La etiqueta puede mostrar un mensaje para escribir el modelo. Puedes pasar suficiente El objeto modelo de sprite de, construir un sistema de partículas para simular el efecto de una escena de lluvia, bosque o nieve.

Ejercicio: Mapa de partículas de la ciudad de China

Primero prepare un archivo de datos Json que contenga la ubicación de cada ciudad en China, como se muestra a continuación, los datos específicos están en la parte inferior del texto
Inserte la descripción de la imagen aquí
Puede preparar una imagen de textura
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

efecto de visualización:
Inserte la descripción de la imagen aquí

Si no usa efectos de mapeo de texturas:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Dificultad: Para compilar un mapa de partículas, se debe obtener el modelo de partículas urbanas correspondiente durante el movimiento del mouse, y aquí se usa Raycaster . Raycasting se usa para seleccionar con el mouse (calcular qué objeto se ha movido el mouse en un espacio tridimensional).

El código final es el siguiente:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>粒子地图</title>
		<!-- 来自three.js文件包 -->
		<script src="../js/three.js" type="text/javascript" charset="utf-8"></script>
		<script src="../js/OrbitControls.js" type="text/javascript" charset="utf-8"></script>
		<style type="text/css">
			*{
     
     
				margin: 0;
				padding: 0;
			}
			#cityInfo {
     
     
				background-color: #F3E9B4;
				position: absolute;
				z-index: 10;
				top: 100px;
				left: 375px;
			}
		</style>
	</head>
	<body>
		<div id="app"></div>
		<div id="cityInfo">全国</div>
		
		<script type="text/javascript">
			
			var scene = new THREE.Scene();
			camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
			render = new THREE.WebGLRenderer({
     
     
				antialias: true
			});
			render.setPixelRatio(window.devicePixelRatio);
			render.setSize(window.innerWidth, window.innerHeight)

			var app = document.getElementById("app");
			app.appendChild(render.domElement);
			/********************************************************/
			var group = new THREE.Group();  // 创建组对象,包含所有精灵对象
			var loader = new THREE.FileLoader().setResponseType('json');  // 文件加载对象
			let texture = new THREE.TextureLoader().load("../img/sprite/sprite.png");  // 粒子贴图
			
			// 进行光线投射来获取鼠标坐标点
			var raycaster = new THREE.Raycaster();
			var mouse = new THREE.Vector2();
			
			// 加载json文件资料
			loader.load('../img/sprite/chinaCity.json', function(data) {
     
     
				//遍历数据
				for (let elem in data) {
     
      
					
					if (elem.indexOf('北京') > -1) {
     
      var color = '#FF0000' } else {
     
      var color = '#1A41E5' }
					// 精灵材质
					let spriteMaterial = new THREE.SpriteMaterial({
     
     
						color: color,
						transparent: true,
						opacity: 0.6,
						map: texture,//设置精灵纹理贴图
					})
					let sprite = new THREE.Sprite(spriteMaterial);   // 创建精灵模型对象
					sprite.title = elem;  // 给精灵模型添加title属性
					group.add(sprite);
					sprite.scale.set(0.5, 0.5, 1);
					//获得城市坐标设置精灵模型对象的位置
					sprite.position.set(data[elem][0], data[elem][1], 0)
				}
				scene.add(group);//把精灵群组插入场景中
				// 中国城市坐标整体的几何中心不在坐标原点,需要适当的平移
				group.position.set(-110, -30, 0);
				let hainanSpriteMaterial = new THREE.SpriteMaterial({
     
     
					map: new THREE.TextureLoader().load("../img/sprite/hainan9.jpg"),//设置精灵纹理贴图
				})
				let hainanSprite = new THREE.Sprite(hainanSpriteMaterial); 
				hainanSprite.position.set(120, 16, 0);
				hainanSprite.scale.set(8, 8);
				hainanSprite.title = '海南九段图'
				group.add(hainanSprite);
			})
			
			function onMouseMove( event ) {
     
     
				// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
				mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
				mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
			}
			window.addEventListener( 'mousemove', onMouseMove, false );
			
			scene.background = new THREE.Color('#fff'); //设置场景颜色
			camera.position.set(20, 20, 60); //设置相机位置
			camera.lookAt(new THREE.Vector3(0, 0, 0))
			// 鼠标控件
			var controls = new THREE.OrbitControls(camera, render.domElement);
			/********************************************************/
			let currentSprite = null, currentSpriteTitle = '';
			function animate(){
     
     
				// 通过摄像机和鼠标位置更新射线
				raycaster.setFromCamera( mouse, camera );
				// 计算物体和射线的焦点    true代表包括后代模型
				let intersects = raycaster.intersectObjects( scene.children, true );
				
				if (intersects.length > 0) {
     
       //判断鼠标移动到的模型数量
					if (currentSprite != intersects && currentSprite) {
     
     
						for (let i = 0; i < currentSprite.length; i++ ) {
     
     
							if (currentSprite[i].object.title.indexOf('北京') > -1) {
     
      currentSprite[i].object.material.color.set( '#FF0000' ); } 
							else {
     
      currentSprite[i].object.material.color.set( '#1A41E5' ); }
							if (currentSprite[i].object.title == '海南九段图') currentSprite[i].object.material.color.set('#FFF')
						}
					}
					for (let i = 0; i < intersects.length; i++ ) {
     
     
						if (intersects[i].object.title == '海南九段图') intersects[i].object.material.color.set('#FFF')
						else intersects[i].object.material.color.set( '#F7AA07' );
					}
					currentSprite = intersects;
					if (!currentSpriteTitle || currentSpriteTitle != currentSprite[0].object.title) {
     
         // 判断是否在城市上,和城市名是否改变
						currentSpriteTitle = currentSprite[0].object.title;
						showCity(currentSpriteTitle, true)
					}
				}
				render.render(scene, camera);
				window.requestAnimationFrame(animate);
			}
			function showCity(name, flag) {
     
       //显示当前鼠标移动到的城市名称
				if (flag) {
     
     
					document.getElementById('cityInfo').style.visibility = 'visible';
					document.getElementById('cityInfo').innerText = name;
				}
				else document.getElementById('cityInfo').style.visibility = 'hidden';
			}
			animate();
		</script>
		
	</body>
</html>

Datos del mapa

Subir a CSDN: ubicación de coordenadas de la ciudad de China

Supongo que te gusta

Origin blog.csdn.net/qq_36171287/article/details/114283487
Recomendado
Clasificación