在 OpenLayers 6 中限制顶点被拖到多边形之外的示例

Example of limiting a vertex from being dragged outside a polygon in OpenLayers6

我有以下情况:

基础多边形是我定义应绘制所有其他多边形的地方。

使用绘制交互时,设置条件选项足以限制点在地图上的位置(在我的例子中,基本多边形)。

问题出在我修改它们的时候。我可以将一个顶点拖到基本多边形之外,我想禁用该行为,但我找不到任何解决方案。

如果我在修改交互中使用绘图交互中的相同条件选项,它只会在放置顶点后禁用拖动。

所以我的问题归结为禁止在指定多边形之外拖动指定多边形内的任何多边形。

编辑 1: 最后我得到了这个:

    const constrainGeometry = (feature: RenderFeature | Feature<Geometry>) => {
      const geometry = feature.getGeometry() as Polygon | undefined;
      if (feature instanceof RenderFeature || geometry === undefined) {
        return geometry;
      }
      const coordinates = geometry.getCoordinates()[0].map((coordinate) => {
        const boundingGeometry = props.boundingFeature.getGeometry();
        if (boundingGeometry) {
          if (boundingGeometry.intersectsCoordinate(coordinate)) {
            return coordinate;
          } else {
            return boundingGeometry.getClosestPoint(coordinate);
          }
        } else {
          return coordinate;
        }
      });
      return new Polygon([coordinates]);
    };

尚未找到使用 TS 的良好解决方案,但目前看来还可以。

拖动时没有适用的条件。您可以使用受约束的几何图形设计特征,并在修改结束时设置该几何图形。

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.8.1/css/ol.css" type="text/css">
    <style>
      html, body, .map {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.8.1/build/ol.js"></script>
  </head>
  <body>
    <div id="map" class="map"></div>
    <script type="text/javascript">

      const boundingPolygon = ol.geom.Polygon.fromCircle(
        new ol.geom.Circle([0, 0], 1e6),
        5
      );

      const constrainGeometry = function(feature) {
        const geometry = feature.getGeometry();
        if (geometry.getType() === 'Polygon') {
          coordinates = geometry.getCoordinates()[0].map(function(coordinate) {
            if (boundingPolygon.intersectsCoordinate(coordinate)) {
              return coordinate;
            } else {
              return boundingPolygon.getClosestPoint(coordinate);
            }
          });
          return new ol.geom.Polygon([coordinates]);
        } else {
          return geometry;
        }
      }

      const style = new ol.style.Style({
        geometry: constrainGeometry,
        fill: new ol.style.Fill({
          color: 'rgba(255, 255, 255, 0.2)',
        }),
        stroke: new ol.style.Stroke({
          color: '#ffcc33',
          width: 2,
        }),
        image: new ol.style.Circle({
          radius: 7,
          fill: new ol.style.Fill({
            color: '#ffcc33',
          }),
        }),
      });

      const vector1 = new ol.layer.Vector({
        source: new ol.source.Vector({
          features: [
            new ol.Feature(boundingPolygon)
          ]
        })
      });

      const vector2 = new ol.layer.Vector({
        source: new ol.source.Vector({
          features: [
            new ol.Feature(ol.geom.Polygon.fromExtent([-5e5, -5e5, 5e5, 5e5]))
          ]
        }),
        style: style
      });

      const map = new ol.Map({
        target: 'map',
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          }),
          vector1,
          vector2
        ],
        view: new ol.View({
          center: [0, 0],
          zoom: 4
        })
      });

      const modify = new ol.interaction.Modify({
        source: vector2.getSource()
      });

      modify.on('modifyend', function (event) {
        event.features.forEach(function (feature) {
          feature.setGeometry(constrainGeometry(feature));
        });
      });

      map.addInteraction(modify);

    </script>
  </body>
</html>