openlayers - 03 点位标注功能

该示例展示了如何在地图上对点位进行标注,点击标注可显示详细信息。通过聚合功能,当缩放时会对点位进行聚合处理。主要步骤包括创建点位要素,设置聚合参数,创建图层,定义详情显示的popover,监听点击事件以更新popover位置,并将覆盖物添加到地图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本例实现对地图中的部分点位进行标注,点击标注可以显示基本信息,缩放后会适当对点位进行聚合

1.实现

1.将获取到的所有点位的坐标数组传入以下函数,根据数据创建点位要素(feature);
2.设置聚合参数(Cluster);
3.创建新的图层,将要素加入图层并配置相关样式;
4.提前定义好详情显示的popover弹窗,创建覆盖物(Overlay),将popover弹窗设置到覆盖物内;
5.监听点击事件获取点击要素的坐标,设置popover覆盖物显示的位置到该座标的位置;
6.将覆盖物添加到地图;

  // 实现标注聚合
  polymerization(dataSource: any[]) {
    var features = new Array(dataSource.length);
    for (var i = 0; i < dataSource.length; i++) {
      var coordinate = [dataSource[i][0], dataSource[i][1]].map(parseFloat);

      var attr = {
        userName: "测试",
        info: "测试点位显示信息",
        coordinate: fromLonLat(coordinate, "EPSG:4326"),
        type: "marker",
      };
      features[i] = new Feature({
        geometry: new Point(coordinate),
        attribute: attr,
      });
    }

    var source = new VectorSource({
      features: features,
    });
    var clusterSource = new Cluster({
      distance: 30, // 超过多少开始聚合
      source: source,
    });

    //加载聚合标注的矢量图层
    var styleCache = {} as any;
    var layerVetor = new VectorLayer({
      source: clusterSource,
      style: function (feature) {
        var size = feature.get("features").length;
        var style = styleCache[size];
        if (!style) {
          style = [
            new Style({
              image: new Icon(
                /** @type {olx.style.IconOptions} */ {
                  anchor: [0.5, 10],
                  anchorOrigin: "top-right",
                  anchorXUnits: "fraction",
                  anchorYUnits: "pixels",
                  offsetOrigin: "top-right",
                  offset: [0, 1], //偏移量设置
                  scale: 1.2, //图标缩放比例
                  opacity: 1, //透明度
                  src: new URL(
                    "../../assets/position-icon.png",
                    import.meta.url
                  ).href, //图标的url
                }
              ),
              text: new Text({
                font: "12px Calibri,sans-serif",
                text: size > 1 ? size.toString() : "",
                fill: new Fill({
                  color: "#eee",
                }),
              }),
            }),
          ];
          styleCache[size] = style;
        }
        return style;
      },
    });

    this.map.addLayer(layerVetor);

    const _this = this;
    var content = document.getElementById("popup-content");
    var title = document.getElementById("popup-title");
    var container: any = document.getElementById("pup-container");
    var position: any = document.getElementById("popup-position");
    var overlay = new Overlay({
      element: container,
      autoPan: true,
      positioning: "bottom-center",
    });
    this.map.on("click", function (evt) {
      title!.innerHTML = ``;
      content!.innerHTML = ``;
      position!.innerHTML = ``;
      // 捕捉feature,用于判断是否点击的是标注点
      let feature = _this.map.forEachFeatureAtPixel(
        evt.pixel,
        function (feature, layerVetor) {
          return feature;
        }
      );

      if (feature) {
        if (!feature.getProperties().features) return;
        var attribute = feature.getProperties().features[0].values_.attribute;
        if (attribute.type !== "marker") return;
        let pLen = feature.getProperties().features.length;
        if (pLen === 1) {
          container.style.display = "block";
          var pixel = _this.map.getEventPixel(evt.originalEvent);
          _this.map.forEachFeatureAtPixel(pixel, function (feature) {
            title!.innerHTML = `<p>项目名称: ${attribute.userName}</p>`;
            content!.innerHTML = `<p>项目描述: ${attribute.info}</p>`;
            position!.innerHTML = `<p>项目坐标: ${attribute.coordinate}</p>`;
            overlay.setPosition(attribute.coordinate);
            _this.map.addOverlay(overlay);
          });
        } else {
          container.style.display = "block";
          var pixel = _this.map.getEventPixel(evt.originalEvent);
          _this.map.forEachFeatureAtPixel(pixel, function (feature) {
            content!.innerHTML = `<p>点位聚合个数: ${pLen}</p>`;
            overlay.setPosition(attribute.coordinate);
            _this.map.addOverlay(overlay);
          });
        }
      } else {
        container.style.display = "none";
      }
    });

注:地图实例化代码见本专题前两章
2.实现效果
在这里插入图片描述
在这里插入图片描述

### 如何在 Vue.js 中使用 OpenLayers 要在 Vue.js 项目中集成 OpenLayers,可以通过以下方式实现: #### 安装依赖 首先,在 Vue.js 项目中安装 OpenLayers 及其他必要的依赖项。如果尚未初始化 Vue.js 项目,则可以按照如下方法快速构建环境[^4]。 ```bash npm create vite@latest vue-openlayers-demo --template vue cd vue-openlayers-demo npm install ``` 接着,安装 OpenLayers 库及其样式文件: ```bash npm install ol npm install @openlayers/vue ``` #### 配置地图组件 为了更高效地管理地图逻辑并保持代码模块化,建议将地图封装为独立的 Vue 组件。以下是创建一个基础地图组件的方法[^2]。 ```vue <template> <div id="map-container"></div> </template> <script> import { Map, View } from 'ol'; import TileLayer from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; export default { name: "OpenMap", mounted() { this.initMap(); }, methods: { initMap() { const map = new Map({ target: 'map-container', layers: [ new TileLayer({ source: new OSM(), }), ], view: new View({ center: [0, 0], zoom: 2, }), }); } } }; </script> <style scoped> #map-container { width: 100%; height: 500px; } </style> ``` 在此示例中,`initMap()` 方法用于初始化地图实例,并将其绑定到 DOM 元素 `#map-container` 上。通过设置视图中心坐标和缩放级别,定义初始显示范围[^3]。 #### 添加标记功能 要向地图添加交互式标记,可利用 OpenLayers 提供的功能扩展现有组件。例如,可通过监听鼠标事件动态生成标注点[^2]。 ```javascript const vectorSource = new VectorSource(); // 向矢量数据源添加新特征 vectorSource.addFeature(new Feature( new Point(fromLonLat([longitude, latitude])) )); this.map.addLayer(new VectorLayer({ source: vectorSource, })); ``` 以上代码片段展示了如何基于地理坐标创建一个新的标记位置,并将其附加至地图上的指定层。 --- ### 使用 OpenLayers Vue 组件库简化开发流程 对于希望进一步减少自定义编码工作量的情况,可以选择引入专门针对 Vue 设计的 **@openlayers/vue** 插件。该插件提供了预设好的 Reactivity API 支持,从而允许开发者更加便捷地操作地图状态变化。 ```vue <template> <o-map :options="{ ...mapOptions }"> <o-layer-tile :source-options="{ url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png' }"/> <!-- 动态加载更多子组件 --> </o-map> </template> <script setup> import { ref } from 'vue'; import '@openlayers/vue/dist/style.css'; const mapOptions = ref({ view: { center: [0, 0], zoom: 2 }, }); </script> ``` 上述模板结构清晰地区分了父级容器与内部嵌套关系,使得维护成本显著降低的同时也增强了项目的可读性和灵活性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大兵的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值