Three.js Miscellaneous Notes (11)-Elves and Particles (Drawing a Map of China)

Introduction to Sprite

The sprite model object Sprite . The sprite model object and the mesh model need to set the material, but the sprite model does not need the programmer to set the geometry, it will be set automatically when the Threejs system renders.

Through the Threejs sprite model, you can set tags for the model objects in the scene, and you can also generate a large number of sprite model objects to simulate a particle system

The three.js sprite model object Sprite is the same as the Threejs mesh model Mesh. The base class is Object3D. For the methods and properties of the sprite model object Sprite, you can view the document Sprite as well as the base class Object3D.

Creating a sprite model object Sprite is the same as creating a mesh model object. You need to create a material object. The difference is that creating a sprite model object does not need to create a geometry object Geometry. In essence, you can understand that a sprite model object has encapsulated a flat rectangular geometry inside. PlaneGeometry, the difference between the rectangular sprite model and the rectangular grid model is that the rectangular plane of the sprite model will always be parallel to the Canvas canvas .

If you want to understand the essence of the sprite model, you can read the official file three.js-master the package source code of the sprite model object \src\objects\Sprite.js, and analyze the source code of the sprite model \src\renderers\webgl\WebGLSpriteRenderer.js.

Sprite和SpriteMaterial

To create a sprite model through Sprite, no geometry is required. You only need to set the parameter of the constructor Sprite to a sprite material SpriteMaterial .

The sprite material object SpriteMaterial can set the color.color, colormap.map, open transparency.transparent, transparency.opacity and other properties like ordinary mesh materials. The base class of the sprite material object SpriteMaterial is the material Material .

Sprite uses

Speaking of the sprite model object, in this case you must be concerned about its purpose. Regarding the purpose, you can use the sprite model as a model label in the 3D scene. The label can display a message for writing the model. You can pass enough The sprite model object of, build a particle system to simulate the effect of a rain, forest, or snow scene.

Exercise: China City Particle Map

First prepare a Json data file containing the location of each city in China, as shown below, the specific data is at the bottom of the text
Insert picture description here
You can prepare a texture picture
Insert picture description here
Insert picture description here

display effect:
Insert picture description here

If you do not use texture mapping effects:
Insert picture description here
Insert picture description here

Difficulty: To compile a particle map, the corresponding urban particle model needs to be obtained during the movement of the mouse, and Raycaster is used here . Raycasting is used for mouse picking (calculating what object the mouse has moved over in three-dimensional space).

The final code is as follows:

<!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>

Map data

Upload to CSDN: China city coordinate location

Guess you like

Origin blog.csdn.net/qq_36171287/article/details/114283487