openlayers 实现区域选择(点击区域高亮,再次点击取消;放大层级显示街道图层,同样可以选择取消)

1.初始化地图

主要通过geojson数据实现边界显示,没有的话可以在这里下载,不过只有区级数据,街道数据自己想办法啦
参考
推荐一个免费下载省-市-区县行政区Shp数据的方法

index.js

import OlMap from '@/components/OlMap/OlMap'; //引入地图的一些方法
import { unByKey } from 'ol/Observable';
let mapListener;
componentWillUnmount() {
	this.initial()
}
initial() {
    this.OlMapView.initMap(id, lng, lat, zoom);//自定义地图id、默认中心点、层级
    if (mapListener) {
      unByKey(mapListener);
    }
    mapListener = this.OlMapView.state.selector.on('select', e => {
      this.handleSelect(e.selected);
    });
    this.OlMapView.addLayerQX_geojson();//通过geojson数据加载边界图层
 }
 handleSelect(features) {
    if (features.length > 0) {
      //获取属性
      let featureInfo = features[0].getProperties();
      console.log('选中的点位信息:', featureInfo);
      this.OlMapView.addArea(featureInfo);//获取点击选择的区域,判断高亮显示还是取消
    }
  }

<OlMap
	id={'OlMapView'}
    ref={node => (this.OlMapView = node)}
    {...this.props}
    onChangeMapState={this.onChangeMapState.bind(this)}
    areaList={areaList}
/>

OlMap.js

let baseMapUrl =baseMapUrl;
let map;
let layers = [];

let areaLayerQX = null;//区域边界图层
let AreaFeatures = null;
let streetLayer = null;//街道边界图层
let areaInfo = null;
let streetInfo = null;

this.state = {
      selector: selector,
     
      loading: false,
      streetLayerVisible: false,
      streetList: [],//保存所选街道信息
    };
initMap(id, lng, lat, zoom) {
    const _this = this;
    centerPoint = lng + '' + lat;
    map = new Map({
      target: id,
      view: new View({
        projection: 'EPSG:4326', //使用这个坐标系
        center: lng && lat ? [lng, lat] : [104.0576, 30.6632], //地图中心点位置
        zoom: zoom ? zoom : 10,
        minZoom: 10,
        maxZoom: 22,
      }),
    });
    this.initLayers();
    map.setLayers(layers);
    map.addInteraction(this.state.selector); //map加载该控件,默认是激活可用的

    //鼠标样式
    map.on('pointermove', e => {
      if (_this.props.drawCircle == true && circleArr.length > 0) {
        _this.removeLabel();
        let radius = getDistance(circleArr[0], e.coordinate);
        console.log(radius, '圆半径');
        const labelElement = document.createElement('div');
        labelElement.className = `${style.highlight_con}`;
        labelElement.innerHTML = `
          <div class=${style.highlight}>半径:${Math.trunc(radius)}米
          </div>`;
        let overlay = new Overlay({
          element: labelElement,
          position: e.coordinate,
          positioning: 'center-center',
          stopEvent: false,
        });
        highlight_overlay.push(overlay);
        map.addOverlay(overlay);
      }
      let pixel = map.getEventPixel(e.originalEvent);
      let feature = map.forEachFeatureAtPixel(pixel, function(feature) {
        return feature;
      });
      if (feature) {
        map.getTargetElement().style.cursor = 'pointer';
      } else {
        map.getTargetElement().style.cursor = 'auto';
      }
    });
    map.on('moveend', function(e) {
      var zoom = map.getView().getZoom(); //获取当前地图的缩放级别
      console.log(zoom, 'zoom');
      if (zoom > 11) {//地图层级超过11级后显示街道图层,隐藏区域图层,反之交换显示
        _this.setState({
          streetLayerVisible: true,
        });
        streetLayer.setVisible(true);
        areaLayerQX.setVisible(false);
      } else {
        streetLayer.setVisible(false);
        areaLayerQX.setVisible(true);
      }
      _this.props.onChangeAreaNoEquip();
      let center = _this.getMapCenter();
      
      centerPoint = center[0] + '' + center[1];
      
    });
    map.on('click', event => {
      console.log('点击坐标=>', event.coordinate, event);      
    });
  }

// 添加底图
  initLayers() {
    let url = `${baseMapUrl}`; // 彩色系

    let resolutions = [
      0.7031250000000002,
      0.3515625000000001,
      0.17578125000000006,
      0.08789062500000003,
      0.043945312500000014,
      0.021972656250000007,
      0.010986328125000003,
      0.005493164062500002,
      0.002746582031250001,
      0.0013732910156250004,
      6.866455078125002e-4,
      3.433227539062501e-4,
      1.7166137695312505e-4,
      8.583068847656253e-5,
      4.2915344238281264e-5,
      2.1457672119140632e-5,
      1.0728836059570316e-5,
      5.364418029785158e-6,
      2.682209014892579e-6,
      1.3411045074462895e-6,
    ];
    let matrixIds = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
    let origin = [-180, 90];
    let tileGrid = new WMTSTileGrid({
      origin: origin, // 原点(左上角)
      resolutions: resolutions, // 分辨率数组
      matrixIds: matrixIds, // 矩阵标识列表,与地图级数保持一致
    });

    // 基础底图
    let baseLayer = new TileLayer({
      source: new XYZ({
        projection: 'EPSG:4326',
        // tileGrid: tileGrid, // 蓝色、白色底图需加此切片方案
        url: ``,
        wrapX: true, // 是否水平包裹地图
      }),
    });
   
    layers.push(baseLayer);
   

    const vectorSourceArea = new VectorSource();//区域图层
    areaLayerQX = new VectorLayer({
      source: vectorSourceArea,
    });
    layers.push(areaLayerQX);

    const vectorSourceStreet = new VectorSource();//街道图层
    streetLayer = new VectorLayer({
      visible: this.state.streetLayerVisible,
      source: vectorSourceStreet,
    });
    layers.push(streetLayer);
  }

2.添加区域边界

OLmap.js

addLayerQX_geojson(name) {
    let _this = this;
    this.setState({
      loading: true,
    });
    if (QXFeatures == null) {
      const json = require('./json/shanghai.json');
      let featuresQX = new GeoJSON().readFeatures(json);
      QXFeatures = featuresQX;

      this.setState({
        loading: false,
      });
      _this.addRegionQX(QXFeatures);
    } else {
      _this.addRegionQX(QXFeatures);
      this.setState({
        loading: false,
      });
    }
  }
  addRegionQX(QXFeatures) {
    let _this = this;
    regionLayerQX.getSource().addFeatures(QXFeatures);
    let features = regionLayerQX.getSource().getFeatures();
    for (let j = 0; j < features.length; j++) {
      let properties = features[j].getProperties();
      features[j].setStyle(
        new Style({
          // 多边形填充颜色
          fill: new Fill({
            color: 'rgba(115,251,253, 0)',
          }),
          // 多边形边框颜色
          stroke: new Stroke({
            color: 'rgba(115,251,253, 0)',
            width: 2,
          }),
          text: new Text({
            //位置
            textAlign: 'center',
            //基准线
            textBaseline: 'bottom',
            fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
            //文字样式
            font: 'normal 24px Alibaba-PuHuiTi-M',
            // font: 'normal 18px 微软雅黑',
            //文本内容
            text: properties.COUTRICT,
            anchorOrigin: 'bottom-right',
            offsetY: 0,
          }),
        })
      );
    }
  }

3.点击区域高亮显示或隐藏

index.js

 handleSelect(features) {
    if (features.length > 0) {
      //获取属性
      let featureInfo = features[0].getProperties();
      console.log('选中的点位信息:', featureInfo);
      this.OlMapView.addArea(featureInfo);//获取点击选择的区域,判断高亮显示还是取消
    }
  }

选择区域的同时加载街道边界,取消区域择清除街道边界
放大层级后会显示街道边界,保存选择街道信息到streetList中,然后筛选出相应的坐标数据,渲染到地图上
OLmap.js

addArea(featureInfo) {
    let _this = this;

    let json = undefined;
    let featuresQX = undefined;
    json = require('./json/shanghai.json');
    let geojson = {
      type: 'FeatureCollection',
      features: [],
    };

    json.features.map(item => {//查找所选区域信息
      if (item.properties.COUTRICT == featureInfo.COUTRICT) {
        geojson.features.push({
          type: 'Feature',
          id: featureInfo.ID,
          geometry: {
            type: 'Polygon',
            coordinates: item.geometry.coordinates,
          },
        });
        featuresQX = new GeoJSON().readFeatures(item);
      }
    });

    if (AreaFeatures == null) {//初次点击
      AreaFeatures = featuresQX;
      areaInfo = featureInfo;
      _this.addRegionHighlight(AreaFeatures);
      _this.addStreet(featureInfo);
    } else {
      if (
        areaInfo &&
        (areaInfo.COUTRICT == featureInfo.COUTRICT )
      ) {//判断当前点击的是否为已经选择过的区域
        if (featureInfo.town) {
          streetLayer.getSource().clear();
          _this.setState({
            loading: false,
          });
          let streetList = this.state.streetList;
          let json = [];
          if (streetList.indexOf(featureInfo.town) > -1) {//如点击的是已选择的街道,删除
            streetList = streetList.filter(item => item != featureInfo.town);
          } else {//反之插入
            streetList.push(featureInfo.town);
          }

          json = streetInfo.features.filter(item => streetList.includes(item.attributes.town));
          let geojson = {
            type: 'FeatureCollection',
            features: [],
          };
          this.setState({
            streetList: streetList,
          });
          for (let i = 0; i < streetInfo.features.length; i++) {
            geojson.features.push({
              type: 'Feature',
              id: i,
              geometry: {
                type: 'Polygon',
                coordinates: streetInfo.features[i].geometry.rings,
              },
              properties: { ...streetInfo.features[i].attributes },
            });
          }
          let streetFeatures = new GeoJSON().readFeatures(geojson);
          streetLayer.getSource().addFeatures(streetFeatures);//渲染高亮显示的街道
          let features = streetLayer.getSource().getFeatures();
          for (let j = 0; j < features.length; j++) {
            let properties = features[j].getProperties();
            if(streetList.includes(properties.town)){
               features[j].setStyle(
              new Style({
                // 多边形填充颜色
                fill: new Fill({
                  color: 'rgba(47, 167, 169, 0.20)',
                }),
                // 多边形边框颜色
                stroke: new Stroke({
                  color: 'rgba(47, 155, 169, 1)',
                  width: 2,
                }),
                text: new Text({
                  //位置
                  textAlign: 'center',
                  //基准线
                  textBaseline: 'bottom',
                  fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
                  //文字样式
                  font: 'normal 24px Alibaba-PuHuiTi-M',
                  //文本内容
                  text: properties.town,
                  anchorOrigin: 'bottom-right',
                  offsetY: 0,
                }),
              })
            );
            }else{
              features[j].setStyle(
                new Style({
                  // 多边形填充颜色
                  fill: new Fill({
                    color: 'rgba(47, 167, 169, 0)',
                  }),
                  // 多边形边框颜色
                  stroke: new Stroke({
                    color: 'rgba(47, 155, 169, 1)',
                    width: 2,
                  }),
                  text: new Text({
                    //位置
                    textAlign: 'center',
                    //基准线
                    textBaseline: 'bottom',
                    fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
                    //文字样式
                    font: 'normal 24px Alibaba-PuHuiTi-M',
                    // font: 'normal 18px 微软雅黑',
                    //文本内容
                    text: properties.town,
                    anchorOrigin: 'bottom-right',
                    offsetY: 0,
                  }),
                })
              );
            }
           
          }
        } else {//点击的是已选择的区域,取消高亮,同时清除街道图层
          AreaFeatures = null;
          areaInfo = null;
          areaLayerQX.getSource().clear();
          streetLayer.getSource().clear();
          this.setState({
            streetList:[]
          })
        }
      } else {
        areaLayerQX.getSource().clear();
        AreaFeatures = featuresQX;
        areaInfo = featureInfo;
        _this.addRegionHighlight(AreaFeatures);
        _this.addStreet(featureInfo);
      }
    }
  }
  addRegionHighlight(QXFeatures) {//高亮区域图层
    let _this = this;
    if (QXFeatures) {
      areaLayerQX.getSource().addFeatures(QXFeatures);
      let features = areaLayerQX.getSource().getFeatures();
      for (let j = 0; j < features.length; j++) {
        let properties = features[j].getProperties();
        features[j].setStyle(
          new Style({
            // 多边形填充颜色
            fill: new Fill({
              color: 'rgba(47, 167, 169, 0.20)',
            }),
            // 多边形边框颜色
            stroke: new Stroke({
              color: 'rgba(47, 155, 169, 1)',
              width: 2,
            }),
            text: new Text({
              //位置
              textAlign: 'center',
              //基准线
              textBaseline: 'bottom',
              fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
              //文字样式
              font: 'normal 24px Alibaba-PuHuiTi-M',
              // font: 'normal 18px 微软雅黑',
              //文本内容
              text: properties.COUTRICT,
              anchorOrigin: 'bottom-right',
              offsetY: 0,
            }),
          })
        );
      }
    }
  }

addStreet(featureInfo) {//渲染街道底图
    let _this = this;
    _this.setState({
      loading: true,
    });
    streetLayer.getSource().clear();
    let regionName = featureInfo.COUTRICT;
    const serviceUrl = serviceUrl ;//获取街道边界数据
    fetch(queryUrl, {
      headers: {},
    })
      .then(response => {
        return response.json();
      })
      .then(json => {
        _this.setState({
          loading: false,
        });
        streetInfo = json;
        let geojson = {
          type: 'FeatureCollection',
          features: [],
        };
        let streetList = [];
        for (let i = 0; i < json.features.length; i++) {
          streetList.push(json.features[i].attributes.town);
          geojson.features.push({
            type: 'Feature',
            id: i,
            geometry: {
              type: 'Polygon',
              coordinates: json.features[i].geometry.rings,
            },
            properties: {
              ...json.features[i].attributes,
              }),
            },
          });
        }
        _this.setState({
          streetList: streetList,
        });
        let streetFeatures = new GeoJSON().readFeatures(geojson);

        streetLayer.getSource().addFeatures(streetFeatures);

        let features = streetLayer.getSource().getFeatures();
        for (let j = 0; j < features.length; j++) {
          let properties = features[j].getProperties();
          features[j].setStyle(
            new Style({
              // 多边形填充颜色
              fill: new Fill({
                color: 'rgba(47, 167, 169, 0.20)',
              }),
              // 多边形边框颜色
              stroke: new Stroke({
                color: 'rgba(47, 155, 169, 1)',
                width: 2,
              }),
              text: new Text({
                //位置
                textAlign: 'center',
                //基准线
                textBaseline: 'bottom',
                fill: new Fill({ color: 'rgba(170, 115, 6, 1)' }),
                //文字样式
                font: 'normal 24px Alibaba-PuHuiTi-M',
                // font: 'normal 18px 微软雅黑',
                //文本内容
                text: properties.town,
                anchorOrigin: 'bottom-right',
                offsetY: 0,
              }),
            })
          );
        }
      });
  }
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenLayers实现上述功能,可以通过以下步骤: 1. 创建一个地图容器和图层 首先,需要在网页中创建一个地图容器和一个图层,可以使用 OpenLayers 的 Map 和 VectorLayer 类来实现: ```javascript var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() // OpenStreetMap 图层 }), new ol.layer.Vector({ source: new ol.source.Vector() // 矢量图层 }) ], view: new ol.View({ center: ol.proj.fromLonLat([0, 0]), // 中心点坐标 zoom: 2 // 缩放级别 }) }); ``` 2. 监听地图的点击事件 接下来,需要为地图添加点击事件监听器,当用户在地图上点击时,会触发该事件: ```javascript map.on('click', function(event) { // 在点击位置添加一个图标 addMarker(event.coordinate); // 在点击位置添加一个圆形区域 addCircle(event.coordinate); }); ``` 3. 添加图标和圆形区域点击事件的处理函数中,需要添加一个图标和一个圆形区域,可以使用 OpenLayers 的 Feature、Point、Circle 和 Style 类来实现: ```javascript function addMarker(coordinate) { // 创建一个 Point 对象 var point = new ol.geom.Point(coordinate); // 创建一个 Feature 对象 var feature = new ol.Feature({ geometry: point }); // 设置 Feature 的样式 feature.setStyle(new ol.style.Style({ image: new ol.style.Icon({ src: 'marker.png', // 图标的 URL anchor: [0.5, 1] // 锚点位置 }) })); // 将 Feature 添加到矢量图层中 var vectorSource = map.getLayers().item(1).getSource(); vectorSource.addFeature(feature); } function addCircle(coordinate) { // 创建一个 Circle 对象 var circle = new ol.geom.Circle(coordinate, 100000); // 半径为 100000 米 // 创建一个 Feature 对象 var feature = new ol.Feature({ geometry: circle }); // 设置 Feature 的样式 feature.setStyle(new ol.style.Style({ stroke: new ol.style.Stroke({ color: 'blue', // 圆形边界线的颜色 width: 2 // 圆形边界线的宽度 }), fill: new ol.style.Fill({ color: 'rgba(0, 0, 255, 0.1)' // 圆形填充颜色,透明度为 0.1 }) })); // 将 Feature 添加到矢量图层中 var vectorSource = map.getLayers().item(1).getSource(); vectorSource.addFeature(feature); } ``` 上述代码中,addMarker 函数用于添加图标,addCircle 函数用于添加圆形区域,其中锚点位置和半径值可以根据实际情况进行调整。在样式的设置中,可以指定圆形边界线和填充的颜色、宽度和透明度等属性。 通过以上步骤,就可以在 OpenLayers 地图上实现点击显示图标和圆形区域的功能了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值