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

如何在React Google Map API中加载GeoJSON并检测用户点击区域

实现点击谷歌地图判断是否在GeoJSON区域内并展示详情

要实现点击位置是否在GeoJSON区域内的判断,核心是利用谷歌地图geometry库的containsLocation方法,结合加载的GeoJSON数据进行匹配,具体实现步骤如下:

1. 添加状态存储点击结果

在组件中新增状态,用于保存点击命中的区域详情:

const [clickedArea, setClickedArea] = useState(null);

2. 完善点击事件处理逻辑

修改onClick函数,遍历GeoJSON的所有区域,通过google.maps.geometry.poly.containsLocation判断点击坐标是否落在区域内,匹配成功后保存该区域的详情:

const onClick = (e) => {
  const clickLatLng = e.latLng;
  let matchedArea = null;

  // 遍历所有GeoJSON区域
  Areas.features.forEach(feature => {
    // 处理Polygon类型区域
    if (feature.geometry.type === 'Polygon') {
      const polygonPath = feature.geometry.coordinates[0].map(coord => 
        new google.maps.LatLng(coord[1], coord[0])
      );
      const polygon = new google.maps.Polygon({ paths: polygonPath });
      
      // 判断点击点是否在多边形内
      if (google.maps.geometry.poly.containsLocation(clickLatLng, polygon)) {
        matchedArea = feature.properties; // 保存区域详情
      }
    }
    // 处理MultiPolygon类型区域
    else if (feature.geometry.type === 'MultiPolygon') {
      feature.geometry.coordinates.forEach(polygonCoords => {
        const polygonPath = polygonCoords[0].map(coord => 
          new google.maps.LatLng(coord[1], coord[0])
        );
        const polygon = new google.maps.Polygon({ paths: polygonPath });
        
        if (google.maps.geometry.poly.containsLocation(clickLatLng, polygon)) {
          matchedArea = feature.properties;
        }
      });
    }
  });

  setClickedArea(matchedArea);
};

3. 渲染区域详情

在组件中添加展示区域详情的模块,根据clickedArea状态动态渲染内容:

// 放在GoogleMap组件下方
<div className="area-detail">
  {clickedArea ? (
    <div>
      <h3>区域详情</h3>
      {Object.entries(clickedArea).map(([key, value]) => (
        <p key={key}><strong>{key}:</strong> {value}</p>
      ))}
    </div>
  ) : (
    <p>点击地图上的区域查看详情</p>
  )}
</div>

完整代码

import React, { useState, useCallback } from "react";
import { GoogleMap, LoadScript } from "@react-google-maps/api";
import Areas from "../GEOJSON.json";

const containerStyle = {
  width: "80%",
  height: "70vh",
};
const GOOGLE_API_KEY = MY_KEY;

function MyComponent() {
  const [map, setMap] = useState(null);
  const [clickedArea, setClickedArea] = useState(null);

  const onLoad = useCallback(function callback(map) {
    setMap(map);
    map.data.addGeoJson(Areas);
  }, []);

  const onUnmount = useCallback(function callback(map) {
    setMap(null);
  }, []);

  const center = {
    lat: 25.2858687,
    lng: 55.3281742,
  };

  const onClick = (e) => {
    const clickLatLng = e.latLng;
    let matchedArea = null;

    Areas.features.forEach(feature => {
      if (feature.geometry.type === 'Polygon') {
        const polygonPath = feature.geometry.coordinates[0].map(coord => 
          new google.maps.LatLng(coord[1], coord[0])
        );
        const polygon = new google.maps.Polygon({ paths: polygonPath });
        
        if (google.maps.geometry.poly.containsLocation(clickLatLng, polygon)) {
          matchedArea = feature.properties;
        }
      } else if (feature.geometry.type === 'MultiPolygon') {
        feature.geometry.coordinates.forEach(polygonCoords => {
          const polygonPath = polygonCoords[0].map(coord => 
            new google.maps.LatLng(coord[1], coord[0])
          );
          const polygon = new google.maps.Polygon({ paths: polygonPath });
          
          if (google.maps.geometry.poly.containsLocation(clickLatLng, polygon)) {
            matchedArea = feature.properties;
          }
        });
      }
    });

    setClickedArea(matchedArea);
  };

  return (
    <React.Fragment>
      <LoadScript
        id="script-loader"
        googleMapsApiKey={GOOGLE_API_KEY}
        language="en"
        region="us"
        libraries={["drawing", "visualization", "geometry", "places"]}
      >
        <GoogleMap
          mapContainerClassName="App-map"
          zoom={12}
          version="weekly"
          mapContainerStyle={containerStyle}
          center={center}
          onLoad={onLoad}
          onUnmount={onUnmount}
          onClick={onClick}
        ></GoogleMap>
      </LoadScript>
      <div className="area-detail" style={{ marginTop: '20px', padding: '10px', border: '1px solid #ddd' }}>
        {clickedArea ? (
          <div>
            <h3>区域详情</h3>
            {Object.entries(clickedArea).map(([key, value]) => (
              <p key={key}><strong>{key}:</strong> {value}</p>
            ))}
          </div>
        ) : (
          <p>点击地图上的区域查看详情</p>
        )}
      </div>
    </React.Fragment>
  );
}

export default React.memo(MyComponent);

注意事项

  • 确保GeoJSON数据的坐标格式为[lng, lat],谷歌地图需要转换为LatLng(lat, lng),因此遍历坐标时要反转顺序。
  • 如果GeoJSON包含其他地理类型(如LineString、Point),可根据需求添加对应的判断逻辑。
  • 若区域数量较多,可优化遍历逻辑,比如先通过地图视野筛选区域,提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:51:01