React Leaflet:动态添加标记

16

如何动态添加标记到React-Leaflet地图?

我想在用户单击地图时添加新的标记,但是我无法使其工作。

import React, { Component } from 'react'
import { render } from 'react-dom';
import Control from 'react-leaflet-control';
import { Map, Marker, Popup, TileLayer, ZoomControl, ScaleControl } from 'react-leaflet';
import './Points.scss'

export default class PointsMap extends Component {
  state = {
    lat: 50.2, 
    lng: 30.2,
    zoom: 13,
  }

  handleClick = (e) => {
    this.addMarker();
  }

  addMarker() {

    // A) Following raises error:  
    var marker3 = L.marker([50.5, 30.5]).addTo(this.refs.map);

    // B) With following marker doesn't appear on map:
    const position2 = [50,30];      
    <Marker map={this.refs.map} position={position2} />
  }

  render () {
    const position = [this.state.lat, this.state.lng]
    return (
      <Map ref='map' center={position} zoom={this.state.zoom} onClick=    {this.handleClick} >
        <ZoomControl position="topright" />
        <ScaleControl position="bottomright" />
        <TileLayer
      attribution='&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
    />
    <Marker map={this.refs.map} position={position} >
      <Popup>
        <span>A pretty CSS3 popup. <br /> Easily customizable.</span>
      </Popup>
    </Marker>
  </Map>

    )
  }
}

addMarker() 函数中,我尝试添加新的标记。我有两种方法来实现这个目标:

A)

 var marker3 = L.marker([50.5, 30.5]).addTo(this.refs.map);

它会引发错误:

 Uncaught TypeError: map.addLayer is not a function
     at NewClass.addTo (leaflet-src.js:3937)
     at PointsMap.addMarker (Points.js?12f5:54)

B)

const position2 = [50,30];      
    <Marker map={this.refs.map} position={position2} />

它不会添加任何新标记,也不会引发任何错误。

您有没有想过如何动态添加/删除标记?

3个回答

29
为了充分利用react-leaflet,您应该考虑如何设计地图渲染方式,以便react生命周期处理点击和标记的显示。React-leaflet为您几乎处理了所有的leaflet gruntwork。
您应该使用组件的状态或道具来跟踪组件正在显示的标记。因此,不要手动调用L.marker,而是应该简单地呈现新的<Marker>组件。
这是在地图上点击后添加标记的react方法:
class SimpleExample extends React.Component {
  constructor() {
    super();
    this.state = {
      markers: [[51.505, -0.09]]
    };
  }

  addMarker = (e) => {
    const {markers} = this.state
    markers.push(e.latlng)
    this.setState({markers})
  }

  render() {
    return (
      <Map 
        center={[51.505, -0.09]} 
        onClick={this.addMarker}
        zoom={13} 
        >
        <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
        />
        {this.state.markers.map((position, idx) => 
          <Marker key={`marker-${idx}`} position={position}>
          <Popup>
            <span>A pretty CSS3 popup. <br/> Easily customizable.</span>
          </Popup>
        </Marker>
        )}
      </Map>
    );
  }
}

这里有一个 jsfiddle 链接:https://jsfiddle.net/q2v7t59h/413/


谢谢。你在我情绪崩溃时帮了我很大的忙。 - catbadger
4
由于 Map 已被 MapContainer 取代,因此不再可能执行此操作。 - VersifiXion

6
对于使用 React Leaflet v3(基于hooks,使用MapContainer而非Map),您可以使用以下代码在单击地图上的点时添加标记:
function LocationMarkers() {
  const initialMarkers: LatLng[] = [new LatLng(51.505, -0.09)];
  const [markers, setMarkers] = useState(initialMarkers);

  const map = useMapEvents({
    click(e) {
      markers.push(e.latlng);
      setMarkers((prevValue) => [...prevValue, e.latlng]);
    }
  });

  return (
    <React.Fragment>
      {markers.map(marker => <Marker position={marker} ></Marker>)}
    </React.Fragment>
  );
}

function LeafletMap() {
  const mapCentre = new LatLng(51.505, -0.09);

  return (
    <MapContainer center={mapCentre}>
      <TileLayer
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <LocationMarkers />
    </MapContainer>
  );
}

这种方法定义了一个名为LocationMarkers的函数,可以在<MapContainer>...</MapContainer>标签中使用。 LocationMarkers使用useMapEvents钩子来监听地图事件(在此示例中为click),并在接收到事件时执行操作。useState用于管理要在地图上显示的标记数组。


5
我使用了下面的代码并成功地运行了它。在此代码中,用户只能在一个位置添加一个标记,它可以更改:
请注意导入leaflet.css文件。
有时在添加leaflet文件后会出现两个关于图像加载的错误。为了解决这些错误,请在导入部分导入marker-icon.png和marker-shadow.png,然后在下面定义L.Marker.prototype.options.icon链接。
如果地图没有显示,请在Map标签中添加高度和宽度(style={{width: '100%',height: '400px'}})作为样式。

import React from 'react';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import icon from 'leaflet/dist/images/marker-icon.png';
import iconShadow from 'leaflet/dist/images/marker-shadow.png';

class OSMap extends React.Component {
    constructor() {
        super();
        this.state = {
            markers: [[35.6892, 51.3890]],
        };
    }

    addMarker = (e) => {
        const { markers } = this.state;
        markers.pop();
        markers.push(e.latlng);
        this.setState({ markers });
    }

    render() {
        let DefaultIcon = L.icon({
            iconUrl: icon,
            shadowUrl: iconShadow
        });
        L.Marker.prototype.options.icon = DefaultIcon;

        return (
            <div>
                <Map
                    center={[35.6892, 51.3890]}
                    onClick={this.addMarker}
                    zoom={13}
                    maxZoom={18}
                    minZoom={5}   
                    style={{width: '100%',height: '400px'}}
                >
                    <TileLayer
                        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                        url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
                    />
                    {this.state.markers.map((position, idx) =>
                        <Marker key={`marker-${idx}`} position={position}></Marker>
                    )}
                </Map>
            </div>
        );
    }
}

export default OSMap;


谢谢,这正是我需要的,让我的图标显示出来了。 - reggie3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接