You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Overlay自动平移时Click误触发Select交互的问题?

问题描述

当为Overlay设置autopan: true时,点击红色圆形标记会出现以下情况:

  • 弹出Overlay
  • autopan功能滚动地图使整个Overlay可见
  • Select交互捕获点击事件,导致矩形变为红色

若autopan设为false,点击红色圆形标记时仅弹出Overlay,不会触发Select交互。

推测原因:点击后autopan移动了地图,当Select交互检查是否处理该点击事件时,原本用于阻止触发的红色标记已移动,无法起到阻止作用。

需在全屏视图查看代码片段,将红色圆形标记置于地图视图底部,使autopan能让整个Overlay显示。请问该如何解决此问题?


代码片段

HTML

<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js"></script>

<div id="map"></div>

<div id="popup" class="popup"></div>

CSS

#map {
  height: 512px;
  width: 1024px;
}

.popup {
  width: 200px;
  height: 300px;
  background-color: blue;
}

JavaScript

//
// Create the Rectangle
//
function createRectangle(layerName) {
  const features = [];

  const feature = {
    type: "Feature",
    geometry: {
      type: "Polygon",
      coordinates: [
        [
          [30, 5],
          [30, 30],
          [85, 30],
          [85, 5]
        ]
      ]
    },
    properties: {
      id: `${layerName}`,
      layerName
    }
  };

  features.push(feature);

  const json = {
    type: "FeatureCollection",
    features
  };

  return json;
}

const rectangle = createRectangle("small");
const rectangleStyle = new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: "hsla(120, 50%, 100%, 1.0)",
    width: 5
  }),
  fill: new ol.style.Fill({
    color: "hsla(120, 50%, 50%, 0.50)"
  })
});

const rectangleVectorLayer = new ol.layer.Vector({
  source: new ol.source.Vector({
    features: new ol.format.GeoJSON({
      featureProjection: "EPSG:4326" // 4326 3857
    }).readFeatures(rectangle)
  }),
  style: (feature) => rectangleStyle,
  zIndex: 4,
  properties: {
    name: "small"
  }
});

//
// Create the marker which will have the overlay attached
//

const markerStyle = new ol.style.Style({
  image: new ol.style.Circle({
    radius: 12,
    fill: new ol.style.Fill({ color: "#e00" }),
    stroke: new ol.style.Stroke({
      color: "black",
      width: 2
    })
  })
});

const markerLayer = new ol.layer.Vector({
  source: new ol.source.Vector({
    features: [
      new ol.Feature({
        geometry: new ol.geom.Point([55, 25])
      })
    ]
  }),
  style: (feature) => markerStyle,
  zIndex: 10
});

//
// Create OSM Layer
//

const osmLayer = new ol.layer.Tile({
  source: new ol.source.OSM()
});

//
// Create the Map
//

const map = new ol.Map({
  target: "map",
  layers: [osmLayer, rectangleVectorLayer, markerLayer],
  view: new ol.View({
    projection: "EPSG:4326",
    center: [55, 30],
    zoom: 5
  })
});

//
//
//

const selectedStyle = new ol.style.Style({
  fill: new ol.style.Fill({
    color: "hsla(0, 50%, 50%, 0.5)"
  }),
  stroke: new ol.style.Stroke({
    color: "hsla(0, 50%, 100%, 1)",
    width: 3
  }),
  zIndex: 1
});

const rectangleLayerInteraction = new ol.interaction.Select({
  style: (feature) => {
    return selectedStyle;
  },
  layers: [rectangleVectorLayer],
  condition: function (e) {
    const isSingleClick = ol.events.condition.singleClick(e);
    let passed = false;

    if (isSingleClick) {
      console.group();
      const features = map.getFeaturesAtPixel(e.pixel, {
        layerFilter: function (l) {
          //console.log(
          //  "rectangle layerFilter",
          //  l.getZIndex(),
          //  rectangleVectorLayer.getZIndex(),
          //  l.getZIndex() > rectangleVectorLayer.getZIndex()
          //);
          return l.getZIndex() > rectangleVectorLayer.getZIndex();
        }
      });
      const noFeatures = features.length === 0;

      passed = isSingleClick && noFeatures;

      //console.log("condition features", features);
      //console.log("condition noFeatures", noFeatures);
      //console.log("condition isSingleClick", isSingleClick);
      //console.log("condition passed", passed);

      console.groupEnd();
    }

    return passed;
  }
});

map.addInteraction(rectangleLayerInteraction);

//
// Add overlay and handler
//

const popup = new ol.Overlay({
  element: document.getElementById("popup"),
  autoPan: true
});

map.addOverlay(popup);

const markerLayerUID = ol.util.getUid(markerLayer);

map.on("click", (e) => {
  const hitFeatures = map.getFeaturesAtPixel(e.pixel, {
    layerFilter: (layer) => {
      return ol.util.getUid(layer) === markerLayerUID;
    }
  });

  //console.log("hitFeatures", hitFeatures);

  if (hitFeatures.length === 1) {
    const position = ol.extent.getBottomLeft(
      hitFeatures[0].getGeometry().getExtent()
    );
    popup.setPosition(position);
  } else {
    popup.setPosition(undefined);
  }
});

内容的提问来源于stack exchange,提问作者Eric G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:53:26