一、项目介绍
在OpenLayers中,我们可以通过点击地图上的要素(Feature)来切换其图标。它的原理就是改变要素的样式(Style)就可以实现切换图标的效果。以下是实现的思路:
- 创建一个地图,并添加一个矢量图层(VectorLayer)来显示要素。
- 创建两个样式:一个用于默认图标,另一个用于点击后的图标。
- 为矢量图层添加点击事件,当点击要素时,检查该要素当前的样式,然后切换到另一个样式。
二、创建图标
js
//矢量图层
this.source = new VectorSource({ wrapX: false });
this.vector = new VectorLayer({
source: this.source,
zIndex: 100,
// declutter: true // 避免图标重叠
});
//地图图层
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.map = new Map({
layers: [this.raster, this.vector],
target: id,
view: new View({
center: fromLonLat(this.center),
zoom: 13,
maxZoom: 22
}),
controls: [], // 不添加任何默认控件
});
//创建要素
const iconFeature = new Feature({
geometry: new Point(fromLonLat(item.lonlat)),
name: item?.name,
id: item?.id ,
type: "icon",
description:item.description,
});
//要素的字体样式
const textStyle = new Style({
text: new Text({
text: iconFeature.get("name"),
textAlign: "center",
textBaseline: "middle",
offsetY: 45, // 文字向下偏移
font: "bold 14px Calibri,sans-serif",
fill: new Fill({
color: "#333",
}),
stroke: new Stroke({
color: "#fff",
width: 1,
}),
}),
});
//要素的图标样式
const iconStyle = new Style({
image: new Icon({
anchor: [0.5, 0.5],
scale: 0.8,
src: url,
}),
});
//添加样式
iconFeature.setStyle([iconStyle, textStyle]);
// 保存原始样式用于选择功能
iconFeature.set('originalStyle', [iconStyle, textStyle]);
iconFeature.set('textStyle', textStyle);
//添加到矢量图层
this.source.addFeature(iconFeature);
三、点击切换图标
我们使用OpenLayers的Select交互来选择地图上的要素。Select交互允许用户通过点击或悬停来选择矢量要素。我们可以通过配置选项来设置选择的方式(例如单击、悬停等),并且可以设置样式来高亮显示选中的要素。
Select的配置参数如下:
- condition : 定义触发选择的条件,默认为
ol/events/condition/singleClick
。可以替换为其他条件,如pointerMove
或自定义函数。 - style: 用于设置选中要素的样式。可以是一个样式对象、样式数组或一个返回样式的函数。
- layers: 指定在哪些图层上进行选择。可以是一个图层数组或一个过滤函数。
- filter : 一个过滤函数,用于确定哪些要素可以被选择。返回
true
表示要素可选择。 - features: 一个要素集合,用于管理选中的要素。如果不指定,交互会创建一个新的集合。
- hitTolerance: 选择要素时鼠标点击的容差范围,单位为像素。默认为0。
- multi : 是否允许多选。默认为
false
。如果为true
,则可以通过按住某个键(如shift
)进行多选。 - toggleCondition : 定义在多选模式下切换要素选择状态的条件。默认为
ol/events/condition/shiftKeyOnly
。 - addCondition : 定义向当前选择中添加要素的条件。默认为
ol/events/condition/never
,因为通常使用toggleCondition
。 - removeCondition : 定义从当前选择中移除要素的条件。默认为
ol/events/condition/never
。 - wrapX : 是否在选择时考虑地图的重复(例如,在世界地图水平重复时)。默认为
true
。
js
import Select from 'ol/interaction/Select'
//创建一个选择交互
const select = new Select({
layers: [this.vector,this.raster],
multi: false
})
//监听选择变化
select.on('select', (e)=>{
console.log('select',e)
//没有选中
e.deselected.forEach(function(feature) {
if(feature.values_?.type!=='icon'){
return
}
const originalStyle = feature.get('originalStyle')
feature.setStyle(originalStyle);
});
//选中
e.selected.forEach(function(feature) {
if(feature.values_?.type!=='icon'){
return
}
const activeStyle = new Style({
image: new Icon({
anchor: [0.5, 0.5],
scale: 0.8,
src: `/images/index/active.png`,
}),
});
const textStyle = feature.get('textStyle')
feature.setStyle([activeStyle,textStyle]);
});
})
//添加到地图
this.map.addInteraction(select)