Three.js杂记(十一)—— 精灵与粒子(绘制中国地图)
精靈模型Sprite
- 精靈模型Sprite簡介
- Sprite和SpriteMaterial
- Sprite用途
- 練習:中國城市粒子地圖
- 地圖數據
精靈模型Sprite簡介
精靈模型對象Sprite。精靈模型對象和網格模型一樣需要設置材質,不過精靈模型不需要程序員設置幾何體,Threejs系統渲染的時候會自動設置。
通過Threejs精靈模型可以給場景中模型對象設置標簽,也可以生成大量精靈模型對象模擬一個粒子系統
Three.js的精靈模型對象Sprite和Threejs的網格模型Mesh一樣都是模型對象,基類都是Object3D,關于精靈模型對象Sprite的方法和屬性除了可以查看文檔Sprite,也可以查看基類Object3D。
創建精靈模型對象Sprite和創建網格模型對象一樣需要創建一個材質對象,不同的地方在于創建精靈模型對象不需要創建幾何體對象Geometry,精靈模型對象本質上你可以理解為已經內部封裝了一個平面矩形幾何體PlaneGeometry,矩形精靈模型與矩形網格模型的區別在于精靈模型的矩形平面會始終平行于Canvas畫布。
如果你想理解精靈模型的本質可以閱讀官方文件three.js-master精靈模型對象的封裝源碼\src\objects\Sprite.js、解析渲染精靈模型的源碼\src\renderers\webgl\WebGLSpriteRenderer.js。
Sprite和SpriteMaterial
通過Sprite創建精靈模型不需要幾何體,只需要給構造函數Sprite的參數設置為一個精靈材質SpriteMaterial即可。
精靈材質對象SpriteMaterial和普通的網格材質一樣可以設置顏色.color、顏色貼圖.map、開啟透明.transparent、透明度.opacity等屬性,精靈材質對象SpriteMaterial的基類是材質Material。
Sprite用途
說到精靈模型對象,這種情況下你肯定關心它的用途,關于用途,你可以在三維場景中把精靈模型作為一個模型的標簽,標簽上可以顯示一個寫模型的信息,你可以通過足夠多的精靈模型對象,構建一個粒子系統,來模擬一個下雨、森林、或下雪的場景效果。
練習:中國城市粒子地圖
先準備一份載有中國各個城市位置的Json數據文件,如下所示即可,具體數據在文本最下方
可以準備一張紋理圖片
顯示效果:
如果不使用紋理貼圖效果:
難點:編寫粒子地圖,在鼠標的移動過程中需要獲取對應的城市粒子模型,在這里使用了光線投射Raycaster。光線投射用于進行鼠標拾取(在三維空間中計算出鼠標移過了什么物體)。
最終代碼如下:
<!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>地圖數據
上傳至CSDN:中國城市坐標位置
總結
以上是生活随笔為你收集整理的Three.js杂记(十一)—— 精灵与粒子(绘制中国地图)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EasyFlash | 让 Flash
- 下一篇: 关于Button控件的CommandNa