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

如何用@react-google-maps/api实现地图点击标记与折线功能?

解决Google Maps React应用中标记与折线不渲染的问题

核心问题分析

  1. 未使用React状态管理坐标:用let coordinates = []声明的数组不是React状态变量,更新后不会触发组件重渲染,导致UI无变化。
  2. 错误的组件渲染方式:在GoogleMap的onClick回调中直接创建<Marker>和<Polyline>组件不会被React挂载,必须在组件的JSX渲染区域内根据状态动态生成。
  3. 折线配置未关联状态:Polyline的options.paths绑定静态数组,状态更新后无法同步到组件。

修改后的完整代码

import React, { useState, useCallback } from 'react'
import { GoogleMap, Marker, Polyline, useJsApiLoader } from '@react-google-maps/api'
import * as key from '../../constants/actions';

const Map = () => {
  // 用useState管理坐标数组,确保更新触发重渲染
  const [coordinates, setCoordinates] = useState([]);
  const { isLoaded } = useJsApiLoader({
    id: 'google-map-script',
    googleMapsApiKey: key.MAPS_API_KEY
  })

  const [map, setMap] = useState(null)
  const onLoad = useCallback(function callback(map) {
    const bounds = new window.google.maps.LatLngBounds(center);
    setMap(map)
  }, [])

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

  const containerStyle = {
    width: '100vw',
    height: '100vh',
    background: 'green'
  }
    
  const center = {
    lat: 44.087585,
    lng: -39.899556
  }
    
  const onLoadMarker = marker => {
    console.log('marker: ', marker)
  }

  const onLoadPoly = polyline => {
    console.log('polyline: ', polyline)
  };

  // 处理地图点击:添加新坐标
  const handleMapClick = (e) => {
    const newCoord = { lat: e.latLng.lat(), lng: e.latLng.lng() };
    setCoordinates(prev => [...prev, newCoord]);
  }

  // 处理标记右键点击:删除该标记及之后的所有坐标
  const handleMarkerRightClick = (index) => {
    setCoordinates(prev => prev.slice(0, index));
  }

  const polylineOptions = {
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35,
    clickable: false,
    draggable: false,
    editable: false,
    visible: true,
    zIndex: 1
  };

  return isLoaded ? (
    <div style={{ padding: '10px' }}>
      <GoogleMap
        mapContainerStyle={containerStyle}
        center={center}
        zoom={3}
        onLoad={onLoad}
        onUnmount={onUnmount}
        onClick={handleMapClick}
      >
        {/* 动态渲染所有标记 */}
        {coordinates.map((coord, index) => (
          <Marker
            key={index}
            position={coord}
            onLoad={onLoadMarker}
            onRightClick={() => handleMarkerRightClick(index)}
          />
        ))}
        {/* 当坐标数≥2时渲染折线 */}
        {coordinates.length >= 2 && (
          <Polyline
            path={coordinates}
            options={polylineOptions}
            onLoad={onLoadPoly}
          />
        )}
      </GoogleMap>
    </div>
  ) : <></>
}

export default Map

关键修改说明

  • 状态化管理坐标:改用useState声明coordinates,通过setCoordinates更新数组,确保触发组件重渲染。
  • 动态渲染标记与折线:在GoogleMap组件内部,通过map循环渲染所有标记,当坐标数≥2时渲染折线。
  • 实现右键删除功能:给每个Marker绑定onRightClick事件,传入对应坐标索引,通过slice(0, index)保留该标记之前的所有坐标。
  • 分离折线配置:将polylineOptions中的paths移除,直接在Polyline组件的path属性绑定状态数组,确保状态更新时折线同步更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:40:18