如何在Next.js中用react-google-maps/api添加一级行政区FeatureLayer样式
解决方案:在react-google-maps/api中高亮选中地点所属的一级行政区
你当前代码的核心问题有两个:
- 未遵循react-google-maps/api的组件体系,直接操作原生Google Maps实例,不符合库的使用规范
- 尝试用地点(如MIT)的placeId匹配一级行政区的placeId,两者并不一致,因此无法触发样式
下面是适配react-google-maps/api的完整实现,包含地理编码反查一级行政区、FeatureLayer样式设置的逻辑:
步骤1:确保依赖安装
npm install @react-google-maps/api # 或 yarn add @react-google-maps/api
步骤2:重构ShowMap.tsx组件
import React, { useRef, useState, useCallback } from "react"; import { GoogleMap, useLoadScript } from "@react-google-maps/api"; import SearchComponent from "./SearchComponent"; const mapContainerStyle = { width: "100%", height: "700px", }; const center = { lat: 23.685, lng: 90.3563 }; const libraries = ["places", "geocoding"]; // 需要加载places和geocoding库 export default function ShowMap({ showPin }: { showPin: boolean }) { const mapRef = useRef<google.maps.Map | null>(null); const featureLayerRef = useRef<google.maps.FeatureLayer | null>(null); const [selectedAdminPlaceId, setSelectedAdminPlaceId] = useState<string | null>(null); // 使用useLoadScript加载地图脚本,替代手动创建script标签 const { isLoaded, loadError } = useLoadScript({ googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!, mapIds: [process.env.NEXT_PUBLIC_MAP_ID!], libraries, }); // 地图加载完成后获取FeatureLayer并设置样式逻辑 const onMapLoad = useCallback((map: google.maps.Map) => { mapRef.current = map; // 获取一级行政区FeatureLayer const featureLayer = map.getFeatureLayer("ADMINISTRATIVE_AREA_LEVEL_1"); featureLayerRef.current = featureLayer; // 初始化样式:默认状态+选中高亮逻辑 featureLayer.style = (options) => { const baseStyle: google.maps.Data.StyleOptions = { fillColor: "#ffffff", fillOpacity: 0.3, strokeColor: "#cccccc", strokeOpacity: 0.8, strokeWeight: 1, }; // 匹配到目标行政区时应用高亮样式 if (options.feature.placeId === selectedAdminPlaceId) { return { ...baseStyle, fillColor: "#ff7859", fillOpacity: 0.8, strokeColor: "#ff7859", strokeWeight: 3, }; } return baseStyle; }; }, [selectedAdminPlaceId]); // 处理搜索:获取选中地点所属的一级行政区placeId const handleSearch = useCallback(async (place: google.maps.places.PlaceResult) => { if (!mapRef.current || !featureLayerRef.current || !place.geometry?.location) return; // 使用地理编码API,根据地点坐标反查所属的一级行政区 const geocoder = new google.maps.Geocoder(); geocoder.geocode( { location: place.geometry.location }, (results, status) => { if (status !== google.maps.GeocoderStatus.OK || !results?.length) return; // 从地理编码结果中提取administrative_area_level_1的placeId const adminAreaResult = results.find(result => result.types.includes("administrative_area_level_1") ); if (adminAreaResult?.place_id) { setSelectedAdminPlaceId(adminAreaResult.place_id); } // 移动地图到选中地点 mapRef.current?.setZoom(12); mapRef.current?.setCenter(place.geometry.location); setTimeout(() => { mapRef.current?.setZoom(8); }, 3000); } ); }, []); if (loadError) return <div>地图加载失败</div>; if (!isLoaded) return <div>加载中...</div>; return ( <> <SearchComponent onSearch={handleSearch} /> <GoogleMap mapContainerStyle={mapContainerStyle} center={center} zoom={10} mapId={process.env.NEXT_PUBLIC_MAP_ID!} onLoad={onMapLoad} /> </> ); }
关键说明
组件体系适配:
- 用
useLoadScript自动加载地图脚本,符合React组件生命周期,替代手动创建script标签 - 通过
GoogleMap组件的onLoad回调获取map实例,避免全局变量污染
- 用
placeId匹配问题解决:
- 搜索到的地点(如MIT)的placeId不属于一级行政区,必须通过地理编码API反查该地点坐标对应的一级行政区信息,提取其合法的placeId
FeatureLayer样式逻辑:
- 在
onMapLoad中初始化样式回调,根据selectedAdminPlaceId动态判断是否高亮目标区域 - 样式回调会自动遍历所有一级行政区Feature,匹配到目标placeId时自动应用高亮样式
- 在
类型安全优化:
- 移除了
//@ts-ignore注释,通过正确的类型声明保证代码类型安全 - 使用
useRef保存map和featureLayer实例,避免全局变量
- 移除了
内容的提问来源于stack exchange,提问作者Anindo Sarker
相关产品推荐
相关产品推荐

