Jelajahi Sumber

地图调整

Hwf 4 bulan lalu
induk
melakukan
33f46c2e95
4 mengubah file dengan 515 tambahan dan 100 penghapusan
  1. 0 0
      src/assets/json/gd.json
  2. 9 0
      src/components/Map/index.vue
  3. 194 45
      src/hooks/AMap/useAMap.ts
  4. 312 55
      src/utils/olMap/olMap.ts

File diff ditekan karena terlalu besar
+ 0 - 0
src/assets/json/gd.json


+ 9 - 0
src/components/Map/index.vue

@@ -352,5 +352,14 @@ onUnmounted(() => {
     padding: 3px 8px;
     border-radius: 4px;
   }
+  :deep(.amap-info-content) {
+    padding: 0;
+  }
+  :deep(.amap-info-close) {
+    display: none;
+  }
+  :deep(.amap-info-sharp) {
+    display: none;
+  }
 }
 </style>

+ 194 - 45
src/hooks/AMap/useAMap.ts

@@ -3,9 +3,10 @@ import { nanoid } from 'nanoid';
 import { deepClone, initDrag } from '@/utils';
 import { mergeGeoJsonPolygons, wgs_gcj_encrypts } from '@/utils/gisUtils';
 import carImg from '@/assets/images/car.png';
+import { iconList } from '@/components/Map/mapData';
 
 export function useAMap(options) {
-  let AMap, map, nowLayer, labelsLayer, scale, cluster;
+  let AMap, map, scale, cluster;
   const markers = {
     point: []
   };
@@ -13,6 +14,12 @@ export function useAMap(options) {
   let addPoints = [];
   let layers = [];
   let defaultLayer;
+  // 标绘图层
+  const plotLayers = [];
+  // 标绘层级
+  let activeLayerkey;
+  // 显示信息框
+  let infoWindow;
   // 初始化事件
   const initMap = (options) => {
     window._AMapSecurityConfig = {
@@ -23,7 +30,19 @@ export function useAMap(options) {
       version: !!options.version ? options.version : '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
       plugins: options.plugins
           ? options.plugins
-          : ['AMap.Scale', 'AMap.RangingTool', 'AMap.MouseTool', 'AMap.PolygonEditor', 'AMap.MarkerCluster', 'AMap.DistrictSearch', 'AMap.MoveAnimation', 'AMap.Driving', 'AMap.Geocoder', 'AMap.PlaceSearch', 'AMap.GeoJSON']
+          : [
+            'AMap.Scale',
+            'AMap.RangingTool',
+            'AMap.MouseTool',
+            'AMap.PolygonEditor',
+            'AMap.MarkerCluster',
+            'AMap.DistrictSearch',
+            'AMap.MoveAnimation',
+            'AMap.Driving',
+            'AMap.Geocoder',
+            'AMap.PlaceSearch',
+            'AMap.GeoJSON'
+          ]
     }).then((res) => {
       AMap = res;
       defaultLayer = AMap.createDefaultLayer();
@@ -115,6 +134,13 @@ export function useAMap(options) {
   const addSearchMarker = (item) => {
     map.setZoom(18);
     map.setCenter(item.lnglat);
+    // 获取到上一次的搜索标记并移除
+    const index = addPoints.findIndex((m) => {
+      return m.dataType === 'search';
+    });
+    if (index > -1) {
+      addPoints.splice(index, 1);
+    }
     addMarker([item], true);
     clickMarker = item;
     options.onMarkerClick(item);
@@ -122,9 +148,11 @@ export function useAMap(options) {
   // 添加多个点
   const addMarker = (points, notClean?: boolean) => {
     if (!notClean) {
-      clearMarker('point');
+      addPoints = points;
+    } else {
+      addPoints.push(...points);
     }
-    addPoints = points;
+    clearMarker('point');
     const count = points.length;
     const _renderClusterMarker = function (context) {
       // 聚合中点个数
@@ -191,7 +219,7 @@ export function useAMap(options) {
     };
     cluster = new AMap.MarkerCluster(
         map, //地图实例
-        points, //海量点数据,数据中需包含经纬度信息字段 lnglat
+        addPoints, //海量点数据,数据中需包含经纬度信息字段 lnglat
         {
           gridSize: 30, //数据聚合计算时网格的像素大小
           renderClusterMarker: _renderClusterMarker, //上述步骤的自定义聚合点样式
@@ -202,56 +230,175 @@ export function useAMap(options) {
       markers['point'].push(item);
     });
   };
-
+  // 添加多个点2 后台做点聚合
+  const addMarker2 = (obj) => {
+    // 新增图层
+    if (!plotLayers['points2']) {
+      plotLayers['points2'] = new AMap.OverlayGroup({
+        zIndex: 10, // 设置图层层级
+        visible: true
+      });
+      map.add(plotLayers['points2']);
+    } else {
+      plotLayers['points2'].clearOverlays();
+      addPoints = [];
+    }
+    let hideInfoFlag = true;
+    Object.keys(obj).forEach((key: string) => {
+      const data = obj[key];
+      if (clickMarker) {
+        const extData = clickMarker.getExtData();
+        if (data.id === extData.id && data.dataType === extData.dataType) {
+          hideInfoFlag = false;
+          data.isHover = true;
+        }
+      }
+      if (data.type === '3') {
+        // 聚合点
+        const div = document.createElement('div');
+        div.style.backgroundColor = 'rgba(78,179,211,.5)';
+        const size = Math.round(25 + Math.pow(1 / 5, 1 / 5) * 20);
+        div.style.width = div.style.height = size + 'px';
+        div.style.border = 'solid 1px rgba(78,179,211,1)';
+        div.style.borderRadius = size / 2 + 'px';
+        div.innerHTML = data.count;
+        div.style.lineHeight = size + 'px';
+        div.style.color = '#ffffff';
+        div.style.fontSize = '12px';
+        div.style.textAlign = 'center';
+        const marker = new AMap.Marker({
+          position: [data.longitude, data.latitude],
+          content: div,
+          anchor: 'center',
+          offset: new AMap.Pixel(0, 0),
+          map: map
+        });
+        marker.setContent(div);
+        marker.on('click', (e) => {
+          const bounds = e.target.getBounds();
+          map.setZoomAndCenter(map.getZoom() + 1, bounds.getCenter());
+        });
+        plotLayers['points2'].addOverlay(marker);
+        addPoints.push(data);
+      } else {
+        // 单个点
+        const iconConfig = iconList[data.dataType] || iconList.common;
+        data.image = iconConfig.image;
+        data.imageHover = iconConfig.imageHover;
+        data.size = iconConfig.size;
+        if (data.materia_name) {
+          data.name = data.materia_name;
+        }
+        if (data.dataType === 43) {
+          data.showName = true;
+        }
+        if (!data.id) {
+          data.id = nanoid(8);
+        }
+        data.lnglat = [data.longitude, data.latitude];
+        const marker = new AMap.Marker({
+          position: [data.longitude, data.latitude],
+          content: getContent(data.isHover ? data.imageHover : data.image, data.size),
+          anchor: 'bottom-center',
+          offset: new AMap.Pixel(0, 0),
+          map: map
+        });
+        marker.setExtData(data);
+        marker.on('click', function (e) {
+          const extData = e.target.getExtData();
+          let index = 0;
+          let index2 = 0;
+          for (let i = 0; i < addPoints.length; i++) {
+            if (addPoints[i].id === extData.id) {
+              marker.setContent(getContent(data.imageHover, data.size));
+              index++;
+            } else if (!!clickMarker) {
+              const extData2 = clickMarker.getExtData();
+              if (addPoints[i].id === extData2.id) {
+                clickMarker.setContent(getContent(extData2.image, extData2.size));
+                index2++;
+              }
+            }
+            if ((!!clickMarker && index === 1 && index2 === 1) || (!clickMarker && index === 1)) {
+              break;
+            }
+          }
+          clickMarker = e.target;
+          options.onMarkerClick(extData);
+        });
+        plotLayers['points2'].addOverlay(marker);
+        addPoints.push(data);
+        if (data.isHover) {
+          clickMarker = marker;
+          options.onMarkerClick(data);
+        }
+      }
+    });
+    if (hideInfoFlag) {
+      clickMarker = null;
+      hideInfo();
+    }
+  };
+  const getContent = (icon: string, size: number[], name?: string, color?: string = '#000') => {
+    let content =
+        '<div style="display: flex;flex-direction: column;align-items: center;justify-content: center;cursor: pointer">' +
+        '<div style="background: url(' +
+        icon +
+        ') no-repeat; width: ' +
+        size[0] +
+        'px;height: ' +
+        size[1] +
+        'px;cursor: pointer; background-size: cover"></div>';
+    if (!!name) {
+      content += '<div style="font-size: 16px;white-space: nowrap; font-weight: bold;color:' + color + '">' + name + '</div>';
+    }
+    content += '</div>';
+    return content;
+  };
   // 清除所有标加
   const clearMarker = (id) => {
     if (!cluster || !markers[id]) return;
     cluster.setMap(null);
     markers[id] = [];
   };
-
-  const handleHover = (extData, dataType) => {
-    map.setZoom(18);
-    map.setCenter([extData.lng, extData.lat]);
-    setTimeout(() => {
-      let index = 0;
-      let index2 = 0;
-      let data = {};
-      for (let i = 0; i < addPoints.length; i++) {
-        if (addPoints[i].id === extData.id.toString() && addPoints[i].dataType === dataType) {
-          addPoints[i].icon = addPoints[i].imageHover;
-          index++;
-          data = addPoints[i];
-        } else if (!!clickMarker) {
-          const extData2 = clickMarker.getExtData ? clickMarker.getExtData() : clickMarker;
-          if (addPoints[i].id === extData2.id) {
-            addPoints[i].icon = addPoints[i].image;
-            index2++;
-          }
-        }
-        if ((!!clickMarker && index === 1 && index2 === 1) || (!clickMarker && index === 1)) {
-          break;
-        }
-      }
-      addMarker(addPoints);
-      options.onMarkerClick(data);
-    }, 2000);
+  const clearMarker2 = (id) => {
+    if (!!plotLayers['points2']) {
+      plotLayers['points2'].clearOverlays();
+      addPoints = [];
+    }
+    clickMarker = null;
+    hideInfo();
   };
-
-  const getMarkers = () => {
-    return markers;
+  let addressMarker;
+  // 设置灾害地点 单独图册
+  const setAddress = (data) => {
+    addressMarker = new AMap.Marker({
+      position: [data.longitude, data.latitude],
+      content: getContent(data.image, data.size, data.name),
+      anchor: 'bottom-center',
+      offset: new AMap.Pixel(0, 16),
+      map: map
+    });
+    if (!plotLayers['address']) {
+      plotLayers['address'] = new AMap.OverlayGroup({
+        zIndex: 10, // 设置图层层级
+        visible: true
+      });
+      map.add(plotLayers['address']);
+    } else {
+      plotLayers['address'].clearOverlays();
+    }
+    plotLayers['address'].addOverlay(addressMarker);
   };
 
-  // 显示信息框
-  let infoWindow;
-  const showInfo = (content, position, isCustom) => {
+  const showInfo = (content, position, offsetY, isCustom) => {
     hideInfo();
     // 实例化InfoWindow
     infoWindow = new AMap.InfoWindow({
       // 完全自定义
       isCustom: isCustom,
       autoMove: false,
-      offset: new AMap.Pixel(0, -20) // 信息窗体的偏移量
+      offset: new AMap.Pixel(0, offsetY ? offsetY : 0) // 信息窗体的偏移量
       // 可以根据需要设置其他InfoWindow的属性
     });
     const lnglat = new AMap.LngLat(position[0], position[1]);
@@ -264,7 +411,7 @@ export function useAMap(options) {
     infoWindow.on('mouseout', () => map.setStatus({ zoomEnable: true }));
   };
 
-  const hideInfo = (e) => {
+  const hideInfo = (e?: any) => {
     map.setStatus({ zoomEnable: true });
     if (!!infoWindow) {
       infoWindow.close();
@@ -273,8 +420,9 @@ export function useAMap(options) {
         for (let i = 0; i < addPoints.length; i++) {
           if (addPoints[i].id === extData.id) {
             addPoints[i].icon = addPoints[i].image;
+            clickMarker.setContent(getContent(addPoints[i].icon, addPoints[i].size));
             clickMarker = null;
-            addMarker(addPoints);
+            // addMarker(addPoints);
             break;
           }
         }
@@ -650,18 +798,19 @@ export function useAMap(options) {
     getMap,
     switchMap,
     addMarker,
+    addMarker2,
     addSearchMarker,
     clearMarker,
-    getMarkers,
+    clearMarker2,
     getScale,
     showInfo,
     hideInfo,
-    handleHover,
     creatMask,
     removeMask,
     creatMask2,
     removeMask2,
     trackPlayback,
-    drawData
+    drawData,
+    setAddress
   };
 }

+ 312 - 55
src/utils/olMap/olMap.ts

@@ -18,16 +18,14 @@ import WMTSCapabilities from 'ol/format/WMTSCapabilities';
 import { Fill, Stroke } from 'ol/style';
 import proj4 from 'proj4';
 import { register } from 'ol/proj/proj4';
-import { defaults } from 'ol/control';
+import { defaults, ScaleLine } from 'ol/control';
 import Vector from 'ol/layer/Vector';
 import SourceVector from 'ol/source/Vector';
 import GeoJSON from 'ol/format/GeoJSON';
-import { fromLonLat } from 'ol/proj';
 import axios from 'axios';
 import { fromExtent } from 'ol/geom/Polygon';
 import { LinearRing, LineString, Polygon } from 'ol/geom';
 import { Graticule } from 'ol/layer';
-import { getPointsCenter, mergeGeoJsonPolygons } from '@/utils/gisUtils';
 import { Cluster } from 'ol/source';
 import CircleStyle from 'ol/style/Circle';
 import Overlay from 'ol/Overlay';
@@ -40,6 +38,8 @@ import * as turf from '@turf/turf';
 import { nanoid } from 'nanoid';
 import carImg from '@/assets/images/car.png';
 import { globalHeaders } from '@/utils/request';
+import { iconList } from '@/views/globalMap/data/mapData';
+import gdJson from '@/assets/json/gd.json';
 
 const tk = 'a8df87f1695d224d2679aa805c1268d9';
 const commonUrl = import.meta.env.VITE_APP_BASE_API2 + 'api/oneShare/proxyHandler/gd/';
@@ -79,7 +79,6 @@ export class olMap {
     icon: '',
     iconName: ''
   };
-  private plot;
   private drawVector;
   private drawTool;
   private vectorLayer;
@@ -87,6 +86,7 @@ export class olMap {
   private maskLayer;
   private maskLayer2;
   // 显示信息框
+  private clickMarker;
   private infoWindow;
   private select;
   // 车辆轨迹
@@ -95,10 +95,14 @@ export class olMap {
   private traceFeature;
   // 自定义绘制结束调用方法
   private drawEndMethod;
-  private selectedFeature;
   private drawing;
   private path;
   private anyLine;
+  private scale;
+  // 标绘图层
+  private plotLayers = {};
+  private addressMarker;
+  private addPoints = [];
 
   constructor(options) {
     this.options = options;
@@ -119,7 +123,8 @@ export class olMap {
     });
     // 初始化比例尺
     if (options.showScale) {
-      // this.map.addControl(new AMap.Scale());
+      this.scale = new ScaleLine();
+      this.map.addControl(this.scale);
     }
     if (options.drawTool?.use) {
       this.initMouseTool(options.drawTool);
@@ -144,44 +149,53 @@ export class olMap {
       condition: click,
       style: null,
       filter: (feature, layer) => {
-        // 只有vectorLayer图层可选择
-        return layer === this.vectorLayer;
+        // 检查当前图层是否在 plotLayers 中
+        return Object.values(this.plotLayers).includes(layer);
       }
     });
     this.map.addInteraction(this.select);
     // 监听Select交互的select事件
     this.select.on('select', (event) => {
-      const selectedFeatures = event.selected[0]; // 获取被选中的要素集合
-      const features = selectedFeatures.get('features');
-      if (selectedFeatures && !!features) {
-        const originalFeature = features[0];
-        const size = features.length;
-        if (size === 1) {
-          if (this.selectedFeature !== originalFeature) {
-            if (this.selectedFeature) {
-              this.selectedFeature.set('icon', this.selectedFeature.get('image'));
-            }
-            this.selectedFeature = originalFeature;
-            const icon = originalFeature.get('imageHover');
-            const extData = originalFeature.get('extData');
-            originalFeature.set('icon', icon);
+      const feature = event.selected[0]; // 获取被选中的要素集合
+      const extData = feature.get('extData');
+      if (!!feature) {
+        if (this.clickMarker) {
+          const selectData = this.clickMarker.get('extData');
+          this.clickMarker.setStyle(
+              new Style({
+                image: new Icon({
+                  src: selectData.image,
+                  scale: selectData.scale,
+                  anchor: [0.5, 0.5],
+                  anchorXUnits: 'fraction',
+                  anchorYUnits: 'fraction'
+                })
+              })
+          );
+        }
+        if (['1', '2'].includes(extData.type)) {
+          // 多点位 单点
+          if (this.clickMarker !== feature) {
+            this.clickMarker = feature;
+            feature.setStyle(
+                new Style({
+                  image: new Icon({
+                    src: extData.imageHover,
+                    scale: extData.scale,
+                    anchor: [0.5, 0.5],
+                    anchorXUnits: 'fraction',
+                    anchorYUnits: 'fraction'
+                  })
+                })
+            );
             options.onMarkerClick(extData);
           }
-        } else {
+        } else if (extData.type === '3') {
           // 聚合要素
-          this.select.getFeatures().clear();
+          // this.select.getFeatures().clear();
           const currentZoom = this.map.getView().getZoom();
           this.map.getView().setZoom(currentZoom + 1);
-          const points = [];
-          features.forEach((feature) => {
-            const geometry = feature.getGeometry(); // 获取要素的几何对象
-            const type = geometry.getType(); // 获取几何类型
-            if (type === 'Point') {
-              points.push(geometry.getCoordinates());
-            }
-          });
-          const newFeature = getPointsCenter(points);
-          this.map.getView().setCenter(newFeature.geometry.coordinates);
+          this.map.getView().setCenter([Number(extData.longitude), Number(extData.latitude)]);
           event.selected = [];
         }
       }
@@ -191,7 +205,11 @@ export class olMap {
     // 添加新的图层
     if (Array.isArray(options.id)) {
       for (const layer of options.id) {
-        await this.formatXml(layer);
+        if (layer.layerType === 'JSON') {
+          await this.createJsonLayer(layer);
+        } else {
+          await this.formatXml(layer);
+        }
       }
     } else if (options.id === 'tianditu') {
       await this.formatXml2();
@@ -202,7 +220,8 @@ export class olMap {
     this.vectorLayer = new VectorLayer({
       source: new VectorSource({
         features: []
-      })
+      }),
+      zIndex: options.zIndex ? options.zIndex : 100
     });
     this.map.addLayer(this.vectorLayer);
     if (typeof this.options.onLoadCompleted === 'function') {
@@ -235,28 +254,40 @@ export class olMap {
   }
   formatXml(options) {
     const xml = new WMTSCapabilities();
-    return this.getCapabilities(options.code).then((res) => {
-      const geoJson = xml.read(res.data);
-      const data = geoJson.Contents.Layer[0];
-      const layerParam = {
-        layerName: data.Abstract,
-        styleName: data.Identifier,
-        tilematrixset: data.TileMatrixSetLink[0].TileMatrixSet,
-        format: data.Format[0]
-      };
-      this.createWmsLayer(options, layerParam);
+    return this.getCapabilities(options.code, options.layerType).then((res) => {
+      if (options.layerType === 'WMTS') {
+        const geoJson = xml.read(res.data);
+        const data = geoJson.Contents.Layer[0];
+        const layerParam = {
+          layerName: data.Abstract,
+          styleName: data.Identifier,
+          tilematrixset: data.TileMatrixSetLink[0].TileMatrixSet,
+          format: data.Format[0]
+        };
+        this.createWmtsLayer(options, layerParam);
+      } else if (options.layerType === 'WFS') {
+        const parser = new DOMParser();
+        const xmlDoc = parser.parseFromString(res.data, 'text/xml');
+        const featureType = xmlDoc.getElementsByTagName('FeatureType')[0];
+        const layerParam = {
+          layerName: featureType.getElementsByTagName('Title')[0].textContent,
+          typeName: featureType.getElementsByTagName('Name')[0].textContent,
+          srsName: featureType.getElementsByTagName('SRS')[0].textContent
+        };
+        this.createWfsLayer(options, layerParam);
+      }
     });
   }
 
   // 请求接口获取地图信息
-  getCapabilities(code) {
-    return axios.get(commonUrl + code + '?SERVICE=WMTS&REQUEST=GetCapabilities', {
+  getCapabilities(code, service) {
+    return axios.get(commonUrl + code + '?SERVICE=' + service + '&REQUEST=GetCapabilities', {
       headers: globalHeaders()
     });
   }
 
-  // 请求地图图片加载图层
-  createWmsLayer(options, layerParam) {
+  // 请求WMTS地图图片加载图层
+  createWmtsLayer(options, layerParam) {
     const source = new WMTS({
       url: commonUrl + options.code,
       crossOrigin: 'Anonymous',
@@ -305,7 +336,50 @@ export class olMap {
     layer.set('id', options.code);
     this.map.addLayer(layer);
   }
+  //
+  createWfsLayer(options, layerParam) {
+    const source = new VectorSource({
+      format: new GeoJSON(),
+      url: `${commonUrl}${options.code}?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&typeName=流域:GEO_BAS_POLYGON&outputFormat=application/json& srsName=EPSG:4490`
+    });
+
+    const vectorLayer = new VectorLayer({
+      source: source,
+      style: new Style({
+        fill: new Fill({
+          color: 'rgba(255, 255, 255, 0.6)'
+        }),
+        stroke: new Stroke({
+          color: '#319FD3',
+          width: 1
+        })
+      })
+    });
 
+    this.map.addLayer(vectorLayer);
+  }
+  // 加载json图层
+  createJsonLayer(layer) {
+    return new Promise((resolve, reject) => {
+      const geojsonParser = new GeoJSON();
+      console.log(this.map.getView().getProjection());
+      const features = geojsonParser.readFeatures(gdJson, {
+        dataProjection: 'EPSG:4326',
+        featureProjection: this.map.getView().getProjection()
+      });
+      const jsonLayer = new VectorLayer({
+        source: new VectorSource({ features }),
+        style: new Style({
+          // 必须设置样式才能显示
+          fill: new Fill({ color: '#ffffff' }),
+          stroke: new Stroke({ color: 'rgba(0,0,0, 1)', width: 1 })
+        }),
+        zIndex: layer.zIndex ? layer.zIndex : -99
+      });
+      this.map.addLayer(jsonLayer);
+      resolve({});
+    });
+  }
   // 初始化绘画工具
   initMouseTool(options) {
     this.drawOptions = {
@@ -659,6 +733,32 @@ export class olMap {
     }
     return style;
   }
+  // 添加搜索的标记的
+  addSearchMarker(item) {
+    const view = this.map.getView();
+    view.setZoom(18);
+    view.setCenter([Number(item.longitude), Number(item.latitude)]);
+    // 获取到上一次的搜索标记并移除
+    const index = this.markers.findIndex((m) => {
+      return m.dataType === 'search';
+    });
+    if (index > -1) {
+      this.markers.splice(index, 1);
+    }
+    if (!this.plotLayers['search']) {
+      this.plotLayers['search'] = new VectorLayer({
+        source: new VectorSource({
+          features: []
+        })
+      });
+      this.map.addLayer(this.plotLayers['search']);
+    } else {
+      this.plotLayers['search'].getSource().clear();
+    }
+    this.addMarker2({ 'search': item });
+    this.clickMarker = item;
+    this.options.onMarkerClick(item);
+  }
   addMarker(points) {
     this.clearMarker();
     const vectorSource = new VectorSource({
@@ -699,19 +799,161 @@ export class olMap {
     this.vectorLayer.setStyle(this.clusterStyle);
     this.vectorLayer.setSource(clusterSource);
   }
+  addMarker2(obj) {
+    this.clearMarker2('point');
+    if (!!this.plotLayers['point']) {
+      this.markers = [];
+    }
+    let hideInfoFlag = true;
+    Object.keys(obj).forEach((key: string) => {
+      const data = obj[key];
+      const name = key === 'search' ? 'search' : 'point';
+      if (this.clickMarker) {
+        const extData = this.clickMarker.get('extData');
+        if (data.id === extData.id && data.dataType === extData.dataType) {
+          hideInfoFlag = false;
+          data.isHover = true;
+        }
+      }
+      if (data.type === '3') {
+        // 聚合点
+        const outerCircle = new CircleStyle({
+          radius: 20,
+          fill: new Fill({
+            color: 'rgba(79, 176, 206, 0.5)'
+          }),
+          stroke: new Stroke({
+            color: 'rgba(79, 176, 206, 1)'
+          })
+        });
+        const feature = new Feature({
+          // 必须是数字类型,字符串不识别
+          geometry: new Point([Number(data.longitude), Number(data.latitude)]),
+          name: data.name,
+          pointer: true,
+          extData: data
+        });
+
+        feature.setStyle(
+            new Style({
+              image: outerCircle,
+              text: new Text({
+                text: data.count.toString(),
+                font: '14px sans-serif',
+                fill: new Fill({
+                  color: '#ffff'
+                })
+              })
+            })
+        );
+        this.plotLayers[name].getSource().addFeature(feature);
+        this.markers.push(data);
+      } else {
+        // 单个点
+        const iconConfig = iconList[data.dataType] || (name === 'search' ? iconList.common2 : iconList.common);
+        data.image = iconConfig.image;
+        data.imageHover = iconConfig.imageHover;
+        data.size = iconConfig.size;
+        if (data.materia_name) {
+          data.name = data.materia_name;
+        }
+        if (data.dataType === 43) {
+          data.showName = true;
+        }
+        if (!data.id) {
+          data.id = nanoid(8);
+        }
+        data.lnglat = [data.longitude, data.latitude];
+        const feature = new Feature({
+          // 必须是数字类型,字符串不识别
+          geometry: new Point([Number(data.longitude), Number(data.latitude)]),
+          name: data.name,
+          pointer: true,
+          extData: data
+        });
+        // 设置自定义属性
+        const img = new Image();
+        img.onload = () => {
+          // 图片加载完成后,可以访问其 width 和 height 属性
+          const scale = data.size[0] ? data.size[0] / img.width : 1;
+          data.scale = scale;
+          feature.set('extData', data);
+          feature.setStyle(
+              new Style({
+                image: new Icon({
+                  src: data.isHover ? data.imageHover : data.image,
+                  scale: scale,
+                  anchor: [0.5, 0.5],
+                  anchorXUnits: 'fraction',
+                  anchorYUnits: 'fraction'
+                })
+              })
+          );
+          this.plotLayers[name].getSource().addFeature(feature);
+          if (data.isHover) {
+            this.clickMarker = feature;
+            this.options.onMarkerClick(data);
+          }
+        };
+        img.src = data.image; // 设置图片的 URL,触发加载
+        this.markers.push(data);
+      }
+    });
+    if (hideInfoFlag) {
+      this.clickMarker = null;
+      this.hideInfo(true);
+    }
+  }
   // 清除所有标加
   clearMarker() {
     if (!this.vectorLayer) return;
     this.vectorLayer.getSource().clear();
   }
-
-  showInfo(content, position, isCustom) {
+  clearMarker2(name) {
+    // 新增图层
+    if (!this.plotLayers[name]) {
+      this.plotLayers[name] = new VectorLayer({
+        source: new VectorSource({
+          features: []
+        })
+      });
+      this.map.addLayer(this.plotLayers[name]);
+    } else {
+      this.plotLayers[name].getSource().clear();
+      // this.clickMarker = null;
+      // this.hideInfo();
+    }
+  }
+  // 设置灾害地点 单独图册
+  setAddress(data) {
+    this.clearMarker2('address');
+    this.addressMarker = new Feature({
+      // 必须是数字类型,字符串不识别
+      geometry: new Point([Number(data.longitude), Number(data.latitude)]),
+      name: data.name,
+      pointer: true,
+      extData: data
+    });
+    this.addressMarker.setStyle(
+        new Style({
+          image: new Icon({
+            src: data.image,
+            scale: [0.288, 0.288],
+            anchor: [0.5, 0.5],
+            anchorXUnits: 'fraction',
+            anchorYUnits: 'fraction'
+          })
+        })
+    );
+    this.plotLayers['address'].getSource().addFeature(this.addressMarker);
+  }
+  showInfo(content, position, offsetY, isCustom) {
     this.hideInfo();
     if (!this.infoWindow) {
       this.infoWindow = new Overlay({
         element: content,
         positioning: 'bottom-center', // 你可以根据需要调整定位方式
-        offset: [0, -10] // 偏移量,用于调整覆盖层相对于要素的位置
+        offset: [0, offsetY ? offsetY : 0] // 偏移量,用于调整覆盖层相对于要素的位置
       });
     }
     this.infoWindow.setPosition(position);
@@ -722,8 +964,20 @@ export class olMap {
   hideInfo(flag?: boolean) {
     this.map.removeOverlay(this.infoWindow);
     this.infoWindow = null;
-    if (!!flag && this.select) {
-      this.select.getFeatures().clear();
+    if (!!flag && this.clickMarker) {
+      const selectData = this.clickMarker.get('extData');
+      this.clickMarker.setStyle(
+          new Style({
+            image: new Icon({
+              src: selectData.image,
+              scale: selectData.scale,
+              anchor: [0.5, 0.5],
+              anchorXUnits: 'fraction',
+              anchorYUnits: 'fraction'
+            })
+          })
+      );
+      this.clickMarker = null;
     }
   }
   /**
@@ -1227,6 +1481,9 @@ export class olMap {
   getMap() {
     return this.map;
   }
+  getScale() {
+    return this.scale;
+  }
   getMouseTool() {
     return this.drawTool;
   }

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini