引言:為什麼要關心 EffectPoint
在地圖應用裏,靜態符號無法表達事件的緊急程度或範圍。為了讓用户立即感知重點,我嘗試了百度地圖 JSAPI 提供的 EffectPoint 特效點。它能把一個地理座標擴展成“會動的”視覺符號,比如雷達掃描、呼吸氣泡或水波擴散。下面從概念、參數、數據綁定到動畫定製,一步步拆解。
EffectPoint 支持哪些特效
EffectPoint 在內部通過 type 字段自動創建不同的材質和幾何體,當前可選值包括,並配上對應的視覺示意:
- Fan:扇形雷達,適合突出掃描扇區。
- Bubble:常規氣泡,表現單點狀態。
- Wave:向外擴散的水波,用於告警覆蓋範圍。
- Breath:呼吸閃爍,突出持續性的監測點(同 Bubble 貼圖可複用)。
- Radar / RadarLayered / RadarSpread:多種雷達層疊動畫,強調多圈掃描。
除此之外,還能開啓 vertexColors 與 vertexSizes,讓每條數據攜帶獨立的顏色或尺寸。材質層統一在構造時綁定到引擎的通用 uniforms,因此所有特效都能隨着引擎渲染循環自動更新。
初始化流程與關鍵參數
EffectPoint 的構造函數接受一個參數對象,其中幾個高頻項值得注意:
color:接受十六進制或rgba字符串,決定初始主色。size:以米為單位的半徑,決定基準尺度。duration:動畫週期,單位毫秒,影響呼吸或擴散速度。keepSize:是否隨相機距離保持屏幕尺寸,適合做 HUD 效果。segmentAngle、sideColor:僅在雷達類特效可用,用於調節扇區角度與底色。
代碼示例:
const engine = new Engine(container, {
rendering: { enableAnimationLoop: true }
});
const effect = engine.add(new EffectPoint({
type: 'Breath',
color: 'rgba(90,160,117,1)',
size: 100,
duration: 5000,
keepSize: true
}));
渲染循環必須開啓動畫模式,否則材質裏的時間 uniform 不會更新,特效靜止。
數據驅動:讓每個點不一樣
在示例中,我用隨機點陣模擬事件分佈。核心做法是:
- 通過數據源(如 GeoJSONDataSource)讀取要素。
- 調用
defineAttribute在數據層聲明color、count等字段的生成邏輯。 - 將
EffectPoint.enableInstanceColor置為true,材質就會按實例顏色渲染。
代碼:
const source = GeoJSONDataSource.fromGeoJSON(mockPoints);
source.defineAttribute('color', () => Math.random() * 0xffffff);
effect.enableInstanceColor = true;
effect.dataSource = source;
解釋:每條記錄都會攜帶顏色,適合表示分類或熱度。
自定義矩陣:控制旋轉與縮放
EffectPoint 繼承自 GeoInstancedPointMesh,也就能覆蓋 getInstanceLocalMatrix,按實例返回一個矩陣。示例裏我用數據中的 count 字段控制縮放,再隨機一個旋轉角度:
effect.getInstanceLocalMatrix = (coords, item) => {
const scale = item.attributes.count;
return Matrix4.compose({
position: [0, 0, 0],
rotationZ: Math.random() * Math.PI,
scale: [scale, scale, scale]
});
};
解釋:這樣同一批特效點在視覺上就會呈現大小、角度完全不同的狀態,避免“克隆體”感。
多種特效組合的實踐
在真實場景裏我會並行創建多個 EffectPoint:
- 第一個用
Breath表示常駐監測點。 - 第二個保持默認類型,模擬普通氣泡。
- 第三個用
Wave表示範圍擴散的事件。
通過不同的數據源、顏色和動畫週期,就能在同一個區域展示層級關係。例如:
const breath = engine.add(new EffectPoint({ type: 'Breath', duration: 5000 }));
breath.dataSource = sourceA;
const bubble = engine.add(new EffectPoint({ size: 120 }));
bubble.dataSource = sourceB;
const wave = engine.add(new EffectPoint({ type: 'Wave', duration: 8000 }));
wave.dataSource = sourceC;
解釋:即便對象類型不同,也共享相同的渲染器和幀循環,不會帶來額外性能負擔。
最佳實踐與避坑
- 確保動畫循環開啓:
rendering.enableAnimationLoop=true是前提。 - 合理的
duration:週期太短會讓動畫閃爍,太長則難以察覺,推薦 3~8 秒區間。 - 調試數據源:先用極少數點驗證材質參數,再逐步擴大,防止一次性加載大量實例導致定位問題。
結語
EffectPoint 把複雜的特效封裝成“擁有多個預設動畫的點對象”。理解它的參數、數據綁定和矩陣自定義後,就能像搭積木一樣快速組合出炫酷的地圖事件層。希望這份筆記能幫你在百度地圖三維場景中快速構建出令人印象深刻的動態點位。