一、项目介绍
产品说地图上只标一个图标,有点看不清在哪里,不够明显,行吧,那我给你加个动画,现在可以看清楚了吧。

二、初始化地图
初始化一个高德地图并定义一个矢量图层,用来展示矢量图标。
js
//高德地图
this.raster = new TileLayer({
source: new XYZ({
url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=2&style=6",
}),
});
//矢量图层
this.source = new VectorSource({ wrapX: false });
this.vector = new VectorLayer({
source: this.source,
zIndex: 100,
declutter: true // 避免图标重叠
});
//初始化地图
this.map = new Map({
layers: [this.raster, this.vector],
target: id,
view: new View({
center: fromLonLat(this.center),
zoom: 13,
}),
controls: [], // 不添加任何默认控件
});
三、创建矢量图标
然后引入icon类型,创建一个icon图标。
方法类别 | 核心类/API | 优点 | 适用场景 | 关键提示 |
---|---|---|---|---|
图片图标 | ol/style/Icon |
简单直接,支持多种图片格式 | 使用静态图片(PNG, JPG, SVG等)作为图标 | 注意调整锚点(anchor)以确保精准定位 |
字体图标 (Canvas) | ol/style/Icon + Canvas |
可动态生成,灵活修改颜色样式 | 需要动态控制颜色、大小的图标 | 将Canvas转换为DataURL使用 |
字体图标 (Text) | ol/style/Text |
无需图片,使用字体文件,矢量缩放清晰 | 使用iconfont等字体图标库 | 确保字体文件正确加载,处理Unicode编码 |
矢量图形 | ol/style/RegularShape |
由代码生成,无需外部资源,可动态设置样式 | 简单几何形状(圆形、方形、星形等) | 可组合使用多种Style实现复杂效果 |
js
//feacture图形
const iconFeature = new Feature({
geometry: new Point(fromLonLat([item.lon,item.lat])),
name: item?.name,
id: item?.id,
type: "icon",
description: description,
item: item,
population: 4000,
rainfall: 500,
});
//样式
const iconStyle = new Style({
image: new Icon({
anchor: [0.5, 0.5],
scale: 0.4,
src: url,
}),
text: new Text({
text: iconFeature.get("name"),
textAlign: "center",
textBaseline: "middle",
offsetY: 30, // 文字向下偏移
font: "bold 14px Calibri,sans-serif",
fill: new Fill({
color: "#333",
}),
stroke: new Stroke({
color: "#fff",
width: 1,
}),
}),
});
iconFeature.setStyle(iconStyle);
this.source.addFeature(iconFeature);
四、闪烁图标
OpenLayers 提供了多种图层事件监听函数,允许你监测图层的状态变化、用户交互以及渲染过程。
事件类型 | 主要事件名称 | 说明 | 适用场景 |
---|---|---|---|
图层状态事件 | loadstart , loadend |
监听图层数据的开始加载和加载完成状态 | 显示加载进度条、处理加载异常 |
visibilitychanged |
图层可见性改变时触发 | 同步控制其他图层显示隐藏、动态调整界面元素 | |
图层操作事件 | addlayer , removelayer |
图层被添加到地图或从地图移除时触发 (注:这些是地图的事件,而非图层自身的事件) | 维护图层列表、记录用户操作日志 |
渲染相关事件 | prerender , postrender |
在图层渲染前后触发 | 进行自定义绘制(如绘制遮罩、高亮)、性能监控 |
precompose , postcompose |
在整个地图合成前后触发 (更像是地图上下文的事件) | 高级效果处理(如滤镜)、地图截图 | |
矢量图层交互事件 | featureselected , featureunselected |
使用 Select 交互时,要素被选中或取消选中时触发 |
显示弹出Popup、展示属性信息、执行自定义操作 |
图层变动事件 | change , change:source , propertychange |
图层属性(如源source )或样式发生变化时触发 |
响应式更新UI、动态调整地图行为 |
OpenLayers 中的 postrender
事件是一个非常重要的图层渲染事件,它在图层每一帧的渲染完成后触发。你可以利用这个事件在现有的图层渲染之上执行自定义的绘制操作、创建动画效果或进行后处理。
js
let radius = 20;
this.vector.on("postrender", listerEvent );
function listerEvent(evt){
const features = this.source.getFeatures();
if (radius >= 50) radius = 20;
var opacity = (50 - radius) * (1 / 50); //不透明度
var pointStyle = new Style({
image: new CircleStyle({
radius: radius,
stroke: new Stroke({
color: "rgba(35,143,196," + opacity + ")",
width: 3 - radius / 50, //设置宽度
}),
offsetY: -20,
}),
});
// 获取矢量要素上下文
let vectorContext = getVectorContext(evt);
vectorContext.setStyle(pointStyle);
radius = radius + 0.3; //调整闪烁速度
features.forEach((feature) => {
if (feature.get("type") === "icon") {
vectorContext.drawGeometry(feature.getGeometry());
}
});
if (features.length) {
this.map.render();
}
}
由于 postrender
事件在每一次图层渲染时都会触发(例如地图移动、缩放时),因此其回调函数的执行效率至关重要。
- 避免昂贵操作 :在回调函数中避免执行复杂的计算、大规模的 DOM 操作或频繁创建大量新对象(如复杂的样式 Style 或几何体 Geometry),否则极易造成页面卡顿。
- 及时清理 :当动画停止或不再需要监听
postrender
时,一定要使用layer.un()
方法移除事件监听器,否则它会继续执行,浪费资源。 - 依赖
frameState
:对于动画,利用event.frameState.time
来计算动画状态,它可以提供一致的时间参考。
js
//根据id删除矢量图标
this.source.forEachFeature((feature) => {
if (feature.get("id") === id) {
this.source.removeFeature(feature);
}
});
//移除监听
this.map.un("postrender",listerEvent);