引言:为什么要关心 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 把复杂的特效封装成“拥有多个预设动画的点对象”。理解它的参数、数据绑定和矩阵自定义后,就能像搭积木一样快速组合出炫酷的地图事件层。希望这份笔记能帮你在百度地图三维场景中快速构建出令人印象深刻的动态点位。