ArcGIS JS API+Three.js實現下雪特效
首先還是來看下效果圖。
通過觀察圖片知道,在三維場景中移動和旋轉地圖,雪花也會有所變化。這是因為本示例中的雪花效果確實是添加進場景中的,是三維空間中的一部分。而有些在三維地圖中展示下雪效果的解決方案只是在地圖的表面添加了一張GIF的動圖,展現不出空間效果。
本示例效果實現的原理是利用Three.js創建我們自定義的三維場景以及渲染器,在場景中添加雪花效果,雪花效果其實就是粒子效果,然后通過ArcGIS API中的externalRenderers
接口注冊到地圖三維場景實例中,就能在地圖三維場景中渲染出雪花了。
創建自定義外部渲染器類
渲染器實例化后至少需要兩個方法:'setup
'方法和'render
'方法,具體的看查看ArcGIS API文檔。下面是部分代碼。
class MyRenderer {
view = null; // 三維地圖視圖實例
renderer = null; // three.js 渲染器
camera = null; // three.js 相機
scene = null; // three.js 中的場景
constructor(options) {
this.view = options.view;
}
setup(context) {
...
}
render(context) {
...
}
}
// 實例化渲染器
let myRenderer = new MyRenderer({ view: view });
// 注冊renderer
externalRenderers.add(view, myRenderer);
在setup
方法中需要利用Three.js創建三維場景以及渲染器,這個具體過程在以前的文章中有寫過,詳細的可查看我的文章《ArcGIS API在視圖中渲染Three.js場景》了解。
創建粒子幾何體
雪花是由許多個點組成的,一片雪花就是一個點,所以我們需要創建一個緩沖幾何體,存儲雪花的位置信息,一個頂點就是一個雪花位置。隨機生成10000個點。
const geometry = new THREE.BufferGeometry();
const vertices = [];
for (let i = 0; i < 10000; i++) {
const x = Math.random() * 1000 - 500;
const y = Math.random() * 1000 - 500;
const z = Math.random() * 1000 - 500;
vertices.push(x, y, z);
}
geometry.setAttribute(
'position',
new THREE.Float32BufferAttribute(vertices, 3)
);
加載雪花的紋理貼圖
實現雪花效果,首先我們要加載雪花的紋理貼圖。Three.js中提供的有紋理加載器TextureLoader
。點擊查看文檔。
const textureLoader = new THREE.TextureLoader();
const sprite = textureLoader.load('./images/雪花紋理圖片.png');
創建材質
因為要創建的物體是用來展示點,所以材質要選點材質PointsMaterial
。點擊查看文檔。
// 創建點材質
const material = new THREE.PointsMaterial({
size: size,
map: sprite,
color: new THREE.Color("rgb(255, 255, 255)"),
blending: THREE.AdditiveBlending, // 融合方式
depthTest: false, // 是否在渲染此材質時啟用深度測試
transparent: true, // 定義此材質是否透明
opacity: 1,
});
創建物體
創建材質后就可以和幾何體創建物體了。需要用到Three.js中的Points
類,點擊查看文檔。
const particles = new THREE.Points(geometry, material);
創建好物體后,需要設置它的位置,設置位置之前就需要將經緯度位置轉換成渲染坐標系中的位置。下面是轉換方法。
/**
* 經緯度坐標點轉換為渲染坐標系中的點坐標
* @param {number} longitude 經度
* @param {number} latitude 緯度
* @param {number} height 高度
* @return {array} 返回渲染坐標系中的點坐標[x, y, z]
*/
pointTransform(longitude, latitude, height) {
let transformation = new Array(16);
// 將經緯度坐標轉換為xy值
let pointXY = webMercatorUtils.lngLatToXY(longitude, latitude);
// 先轉換高度為0的點
externalRenderers.renderCoordinateTransformAt(
this.view,
[pointXY[0], pointXY[1], height], // 坐標在地面上的點[x值, y值, 高度值]
this.view.spatialReference,
transformation
);
return [transformation[12], transformation[13], transformation[14]];
}
設置位置:
const location = pointTransform(經度, 緯度, 高度);
particles.position.set(...location);
添加動畫
現在,就可以在地圖三維場景中正確的位置上看到雪花效果了,但它是靜止的。想要它動起來也很簡單,只需在render
方法中改變geometry中每個頂點的位置就行了,因為每一個頂點位置就代表一片雪花,改變頂點位置,雪花的位置也會隨之改變。
完整代碼
如需查看示例效果可點擊下載完整代碼。
如果該文章對您有所幫助,請您一定不要吝嗇您的鼓勵。點贊、評論、分享、收藏、打賞都是您對我的鼓勵和支持。
如果您有GitHub
賬號,還可以關注我~
最后,感謝大家的閱讀,如有錯誤,還請各位批評指正。