openlayer点击切换图标

一、项目介绍

在OpenLayers中,我们可以通过点击地图上的要素(Feature)来切换其图标。它的原理就是改变要素的样式(Style)就可以实现切换图标的效果。以下是实现的思路:

  1. 创建一个地图,并添加一个矢量图层(VectorLayer)来显示要素。
  2. 创建两个样式:一个用于默认图标,另一个用于点击后的图标。
  3. 为矢量图层添加点击事件,当点击要素时,检查该要素当前的样式,然后切换到另一个样式。

二、创建图标

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的配置参数如下:

  1. condition : 定义触发选择的条件,默认为 ol/events/condition/singleClick。可以替换为其他条件,如 pointerMove 或自定义函数。
  2. style: 用于设置选中要素的样式。可以是一个样式对象、样式数组或一个返回样式的函数。
  3. layers: 指定在哪些图层上进行选择。可以是一个图层数组或一个过滤函数。
  4. filter : 一个过滤函数,用于确定哪些要素可以被选择。返回 true 表示要素可选择。
  5. features: 一个要素集合,用于管理选中的要素。如果不指定,交互会创建一个新的集合。
  6. hitTolerance: 选择要素时鼠标点击的容差范围,单位为像素。默认为0。
  7. multi : 是否允许多选。默认为 false。如果为 true,则可以通过按住某个键(如 shift)进行多选。
  8. toggleCondition : 定义在多选模式下切换要素选择状态的条件。默认为 ol/events/condition/shiftKeyOnly
  9. addCondition : 定义向当前选择中添加要素的条件。默认为 ol/events/condition/never,因为通常使用 toggleCondition
  10. removeCondition : 定义从当前选择中移除要素的条件。默认为 ol/events/condition/never
  11. 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)
相关推荐
向葭奔赴♡8 小时前
前端框架学习指南:提升开发效率
前端·javascript·vue.js
一个不爱写代码的瘦子8 小时前
Map、weakMap和Set、weakSet
前端·javascript
_AaronWong8 小时前
Electron视频黑屏之谜:从H265编码到GPU禁用的深度排查
前端·electron·视频编码
Icoolkj8 小时前
npm、npx、pnpm 深度解析:从原理到实战的全方位指南
前端·npm·node.js
Dcc8 小时前
@tanstack/react-query详解 🔥🔥🔥React的异步数据管理神器
前端·react.js
尘埃不入你眼眸8 小时前
powerShell无法执行npm问题
前端·npm·node.js
我是一只懒羊羊8 小时前
从零搭建 Node.js企业级 Web 服务器:自定义服务&数据请求
前端·node.js·全栈
itslife8 小时前
vite 源码 -
前端·javascript
我有一棵树8 小时前
npm uninstall 执行的操作、有时不会删除 node_modules 下对应的文件夹
前端·npm·node.js