Openlayers示例9 | Box Selection

Box Selection

这个例子展示了如何使用DragBox交互来选择功能。选中的特性被添加到选中交互(ol/interaction/ select)的特性叠加层中以高亮显示。

使用Ctrl+拖动(命令+拖动在Mac上)来绘制框。

数据url:
https://openlayers.org/data/vector/ecoregions.json

<!DOCTYPE html>
<html lang="zn">

<head>
  <meta charset="UTF-8">
  <!-- 引入OpenLayers CSS样式 -->
  <link rel="stylesheet"
    href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css">
  <!-- 引入OpenLayers JS库 -->
  <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>
  <!-- css代码 -->
  <style>
    .map {
      width: 100%;
      height: 600px;
    }
  </style>
  <title>Box Selection</title>
</head>
<body>
  <div id="map" class="map"></div>
  <div>Selected regions: <span id="info">None</span></div>
</body>
<script>
  const vectorSource = new ol.source.Vector({
    url: 'https://openlayers.org/data/vector/ecoregions.json',
    format: new ol.format.GeoJSON(),
  });

  const style = new ol.style.Style({
    fill: new ol.style.Fill({
      color: '#eeeeee',
    }),
  });

  const map = new ol.Map({
    layers: [
      new ol.layer.Vector({
        source: vectorSource,
        background: '#1a2b39',
        style: function (feature) {
          const color = feature.get('COLOR_BIO') || '#eeeeee';
          style.getFill().setColor(color);
          return style;
        },
      }),
    ],
    target: 'map',
    view: new ol.View({
      center: [0, 0],
      zoom: 2,
      constrainRotation: 16,
    }),
  });

  // 定义被选中的面图形的样式
  const selectedStyle = new ol.style.Style({
    fill: new ol.style.Fill({
      color: 'rgba(255, 255, 255, 0.6)',
    }),
    stroke: new ol.style.Stroke({
      color: 'rgba(255, 255, 255, 0.7)',
      width: 3,
    }),
  });

  // 处理单击的普通选择交互
  const select = new ol.interaction.Select({
    style: function (feature) {
      const color = feature.get('COLOR_BIO') || '#eeeeee';
      selectedStyle.getFill().setColor(color);
      return selectedStyle;
    },
  });
  map.addInteraction(select);

  const selectedFeatures = select.getFeatures();

  // 一个通过绘制框来选择功能的DragBox交互
  const dragBox = new ol.interaction.DragBox({
    condition: ol.events.condition.platformModifierKeyOnly,
  });

  map.addInteraction(dragBox);

  dragBox.on('boxend', function () {
    const extent = dragBox.getGeometry().getExtent();
    const boxFeatures = vectorSource
      .getFeaturesInExtent(extent)
      .filter((feature) => feature.getGeometry().intersectsExtent(extent));

    // 与盒形几何相交的特征被添加到所选特征集合中

    // 如果视图不是斜旋转的盒子几何和它的范围是相等的,所以相交的特征可以直接添加到集合
    const rotation = map.getView().getRotation();
    const oblique = rotation % (Math.PI / 2) !== 0;

    // 当视图被倾斜旋转时,框的范围将超过它的几何形状,所以框和候选特征几何形状都围绕一个共同的锚旋转,以确认,当框几何形状与其范围对齐时,几何形状相交
    if (oblique) {
      const anchor = [0, 0];
      const geometry = dragBox.getGeometry().clone();
      geometry.rotate(-rotation, anchor);
      const extent = geometry.getExtent();
      boxFeatures.forEach(function (feature) {
        const geometry = feature.getGeometry().clone();
        geometry.rotate(-rotation, anchor);
        if (geometry.intersectsExtent(extent)) {
          selectedFeatures.push(feature);
        }
      });
    } else {
      selectedFeatures.extend(boxFeatures);
    }
  });

  // 当绘制一个新的方框和在地图上单击时,清除选择
  dragBox.on('boxstart', function () {
    selectedFeatures.clear();
  });

  const infoBox = document.getElementById('info');

  selectedFeatures.on(['add', 'remove'], function () {
    const names = selectedFeatures.getArray().map(function (feature) {
      return feature.get('ECO_NAME');
    });
    if (names.length > 0) {
      infoBox.innerHTML = names.join(', ');
    } else {
      infoBox.innerHTML = 'None';
    }
  });
</script>
</html>
posted @ 2022-03-20 16:42  槑孒  阅读(209)  评论(0编辑  收藏  举报