当前位置: 首页 > 知识库问答 >
问题:

如何访问要在infobox中显示的重叠geojson/多边形

颛孙建业
2023-03-14

我正在使用谷歌地图应用编程接口使用地理JSON数据层将多个多边形加载到地图中。这些多边形中的一些在某些区域重叠。当用户单击多个多边形内部的点时,我希望通过单击事件在InfoBox中显示属性(名称、标签等)。

我想显示给定点的所有多边形的属性。当前,当我单击一个点时,我只能看到一个多边形,尽管该点位于多个多边形的内部。

如何使用Google Maps API v3访问所有多边形的所有属性?

const map = useGoogleMap(); // google map instance
const polygons; // an array of polygons, example snippet below. 

map.data.addGeoJson(polygons);

map.data.addListener('click', function(event) {
   // how can i access other features underneath this clicked point
   console.log(event.feature); // only returns "Geofence 1"
})

示例GeoJson:

polygons = {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
      "name": "Geofence 1"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -8.96484375,
              -9.96885060854611
            ],
            [
              3.955078125,
              -9.96885060854611
            ],
            [
              3.955078125,
              -0.17578097424708533
            ],
            [
              -8.96484375,
              -0.17578097424708533
            ],
            [
              -8.96484375,
              -9.96885060854611
            ]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
      "name": "Geofence 2"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -6.591796875,
              -8.320212289522944
            ],
            [
              2.197265625,
              -8.320212289522944
            ],
            [
              2.197265625,
              -1.9332268264771106
            ],
            [
              -6.591796875,
              -1.9332268264771106
            ],
            [
              -6.591796875,
              -8.320212289522944
            ]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
      "name": "Geofence 3"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -4.39453125,
              -6.926426847059551
            ],
            [
              0.263671875,
              -6.926426847059551
            ],
            [
              0.263671875,
              -3.337953961416472
            ],
            [
              -4.39453125,
              -3.337953961416472
            ],
            [
              -4.39453125,
              -6.926426847059551
            ]
          ]
        ]
      }
    }
  ]
}

共有2个答案

池赞
2023-03-14

我能够让这个POC与React一起工作,并为下一个可能感兴趣的人分享:

import { InfoWindow, useGoogleMap } from '@react-google-maps/api';

export const GeofencesContainer = () => {
  const map = useGoogleMap();
  // geofence = geoJSON feature collections
  const [geofenceClickEventLatLng, setGeofenceClickEventLatLng] = useState({});
  const [geofencesProperties, setGeofencesProperties] = useState([]);
  const [isInfoWindowOpen, setIsInfoWindowOpen] = useState(false);
  const [polygonArray, setPolygonArray] = useState([]);
  const ref = useRef();

  useEffect(() => {
    let addFeatureListener;
    const getGeofences = async () => {
      if (true) {
        if (ref.current !== 'geofenceEnabled') {
          // get geofences from api
          const geofences = await fetch.getGeofences(); 

          // a listener to add feature, where we create a google.maps.polygon for every added feature, then add it to the polygon array
          const addedPolygons = [];
          addFeatureListener = map.data.addListener('addfeature', e => {
            const featureGeometry = e.feature.getGeometry().getArray();

            // for each geometry get the latLng array, which will be used to form a polygon
            featureGeometry.forEach(latLngArray => {
              const polygon = new window.google.maps.Polygon({
                map,
                paths: latLngArray.getArray(),
                strokeWeight: 1,
                fillColor: 'green',
                clickable: false,
                name: e.feature.getProperty('name')
              });
              addedPolygons.push(polygon);
            });
            setPolygonArray(addedPolygons);
          });

          // add the polygon to the map data layer (this will show the polygon on the map and cause the addfeature listener to fire)
          map.data.addGeoJson(geofences);
          map.data.setStyle({ fillColor: 'green', strokeWeight: 1 });
          // we set map data to null so that we don't end up with 2 polygons on top of each other
          map.data.setMap(null);
          ref.current = 'geofenceEnabled';
        }
      } else {
        ref.current = null;
        for (const polygon of polygonArray) {
          polygon.setMap(null);
        }
        setIsInfoWindowOpen(false);
      }
    };
    getGeofences();

    return () => {
      if (addFeatureListener) {
        addFeatureListener.remove();
      }
    };
  }, [activeKmls]);

  useEffect(() => {

    let clickListener;
    if (true) {
      // a listener on click that checks whether the point is in a polygon and updates the necessary state to show the proper info window
      clickListener = map.addListener('click', function(event) {
        // this state is updated to identify the place where the info window will open
        setGeofenceClickEventLatLng(event.latLng);

        // for every polygon in the created polygons array check if it includes the clicked point, then update what to display in the info window
        const selectedGeofences = [];
        for (const polygon of polygonArray) {
          if (window.google.maps.geometry.poly.containsLocation(event.latLng, polygon)) {
            const name = polygon.name;
        
            selectedGeofences.push({ key: name, name });
          }
        }
        if (selectedGeofences.length) {
          setIsInfoWindowOpen(true);
        } else {
          setIsInfoWindowOpen(false);
        }
        setGeofencesProperties(selectedGeofences);
      });
    }

    return () => {
      if (clickListener) {
        clickListener.remove();
      }
    };
  }, [activeKmls, polygonArray, altitudeUnit, map]);

  return (
    <Fragment>
      {isInfoWindowOpen && (
        <InfoWindow
          position={geofenceClickEventLatLng}
          onCloseClick={() => setIsInfoWindowOpen(false)}
          zIndex={0}
          options={{ maxWidth: '450' }}
        >
          <Fragment>
            {geofencesProperties.map(geofenceProperties => {
              return (
                <Fragment key={geofenceProperties.key}>
                  <Title level={4}>{geofenceProperties.name}</Title>
                </Fragment>
              );
            })}
          </Fragment>
        </InfoWindow>
      )}
    </Fragment>
  );
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
孙朗
2023-03-14

一种选择是在几何图形库中使用containsLocation方法。

containsLocation(点、多边形)参数
点:LatLng
多边形:多边形
返回值:布尔值
计算给定点是否位于指定多边形内。

不幸的是,这只适用于本机google.maps.Polygon对象,而不是Data。多边形对象。将功能中的数据转换为本机google.maps.Polygon对象,将它们推送到数组上,然后处理数组以查看单击位于哪个多边形中。

  1. 为输入中的每个多边形创建google.maps.Polygon(仅假设多边形)
  var polygonArray = [];
  map.data.addListener('addfeature', function(e) {
    e.feature.getGeometry().getArray().forEach(function(latLngArry){
      const polygon = new google.maps.Polygon({
        map: map,
        paths: latLngArry.getArray(),
        clickable: false,
        name: e.feature.getProperty("name") // save the data we want to output as an attribute
      })
      polygonArray.push(polygon);
    })
  map.addListener('click', function(event) {
    var content = "";
    for (var i=0;i<polygonArray.length;i++) {
       if (google.maps.geometry.poly.containsLocation(event.latLng, polygonArray[i])) {
          if (content.length!=0) 
            content+=" : "
          content += polygonArray[i].name;
       }
    }
    console.log(content);
  })

概念证明小提琴

// This example uses the Google Maps JavaScript API's Data layer
// to create a rectangular polygon with 2 holes in it.
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"));
  const infowindow = new google.maps.InfoWindow();
  var bounds = new google.maps.LatLngBounds();
  var polygonArray = [];
  map.data.addListener('addfeature', function(e) {
    console.log(e.feature.getGeometry().getArray().length);
    e.feature.getGeometry().getArray().forEach(function(latLngArry) {
      console.log(latLngArry.getArray())
      const polygon = new google.maps.Polygon({
        map: map,
        paths: latLngArry.getArray(),
        clickable: false,
        name: e.feature.getProperty("name")
      })
      polygonArray.push(polygon);
    })
    processPoints(e.feature.getGeometry(), bounds.extend, bounds);
    map.fitBounds(bounds);
  });
  const features = map.data.addGeoJson(polygons);
  map.data.setMap(null);
  map.addListener('click', function(event) {
    var content = "";
    for (var i = 0; i < polygonArray.length; i++) {
      if (google.maps.geometry.poly.containsLocation(event.latLng, polygonArray[i])) {
        if (content.length != 0)
          content += " : "
        content += polygonArray[i].name;
      }
    }
    console.log(content);
    document.getElementById('info').innerHTML = content;
    infowindow.setPosition(event.latLng);
    if (content.length == 0) content = "no GeoFence";
    infowindow.setContent(content);
    infowindow.open(map);
  })

  function processPoints(geometry, callback, thisArg) {
    if (geometry instanceof google.maps.LatLng) {
      callback.call(thisArg, geometry);
    } else if (geometry instanceof google.maps.Data.Point) {
      callback.call(thisArg, geometry.get());
    } else {
      geometry.getArray().forEach(function(g) {
        processPoints(g, callback, thisArg);
      });
    }
  }
}
const polygons = {
  "type": "FeatureCollection",
  "features": [{
      "type": "Feature",
      "properties": {
        "name": "Geofence 1"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [-8.96484375, -9.96885060854611],
            [
              3.955078125, -9.96885060854611
            ],
            [
              3.955078125, -0.17578097424708533
            ],
            [-8.96484375, -0.17578097424708533],
            [-8.96484375, -9.96885060854611]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "Geofence 2"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [-6.591796875, -8.320212289522944],
            [
              2.197265625, -8.320212289522944
            ],
            [
              2.197265625, -1.9332268264771106
            ],
            [-6.591796875, -1.9332268264771106],
            [-6.591796875, -8.320212289522944]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "Geofence 3"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [-4.39453125, -6.926426847059551],
            [
              0.263671875, -6.926426847059551
            ],
            [
              0.263671875, -3.337953961416472
            ],
            [-4.39453125, -3.337953961416472],
            [-4.39453125, -6.926426847059551]
          ]
        ]
      }
    }
  ]
}
/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */

#map {
  height: 90%;
}


/* Optional: Makes the sample page fill the window. */

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<!DOCTYPE html>
<html>

<head>
  <title>Data Layer: Polygon</title>
  <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
  <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=&v=weekly" defer></script>
  <!-- jsFiddle will insert css and js -->
</head>

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

</html>
 类似资料:
  • 本文向大家介绍双边距重叠问题(外边距折叠)相关面试题,主要包含被问及双边距重叠问题(外边距折叠)时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 多个相邻(兄弟或者父子关系)普通流的块元素垂直方向marigin会重叠 折叠的结果为: 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。 两个外边距一正一负时,折叠结果是两者的

  • 问题内容: 我有一种情况,我需要在堆叠的多条形图-nvd3图中显示每个堆栈的值,因为我们可以在离散值-nvd3图中显示值。 我了解,“ showvalue”用于离散条形控制器中,是否可以在堆叠图中使用,如果没有,请提出替代解决方案。 提前致谢 问题答案: 目前不可能。该选项仅在离散条形图中可用。 从维护者处: 我们没有这种能力。堆叠/分组图表还具有复杂的动画,因此这很棘手。我们改用工具提示。 来源

  • 问题内容: 我正在使用MongoDB开发地理空间网络应用程序。我在具有不同类别(,等)的集合上有很多多边形,我想知道哪个是某个多边形,但是在某些情况下,邻居的边界碰到了多边形的边界,所以当我查询十字路口,我有2个国家。 我想计算该州与两个国家之间的重叠百分比,以了解哪个是父级。我一直在寻找,但是我没有找到具有这种操作的任何库,并且我做这种算法不是很好。 编辑:添加更多上下文 这是我正在使用的模型

  • 我需要在Mapbox Android SDK地图上绘制一个带孔的GeoJSON多边形。 正如GeoJSON规范所说, 对于类型“多边形”,“坐标”成员必须是线性环坐标数组的数组。对于有多个环的多边形,第一个必须是外环,其他必须是内环或孔。 在手册Mapbox JS和Mapbox GL JS中,加载GeoJSONs由库本身处理。从这把小提琴中可以看出,lib考虑了内环,因此正确地绘制了孔。 当我查看

  • 有没有办法在python中合并两个重叠的GEOJSON多边形,返回一个合并的GEOJSON对象?

  • 本文向大家介绍leaflet加载geojson叠加显示功能代码,包括了leaflet加载geojson叠加显示功能代码的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了leaflet加载geojson叠加显示功能代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 geojson需要先制作shp,然后导入下面网站生成geojson。 ht