#javascript #reactjs #leaflet #react-leaflet
#javascript #reactjs #листовка #реагировать-листовка #реагировать-листовка-v3
Вопрос:
Я хочу иметь кнопку вне карты, которая изменяет вид на другие координаты.
Есть ли какой-либо способ заставить экземпляр mapContainer вызывать свои функции? Или как я могу реализовать эту функцию?
Я пытался получить его с помощью ссылки, но это не работает. Вот мой текущий код
const zoom = 13;
function Map({ regionCoord, regionName }) {
const mapRef = useRef();
function handleFlyToClick() {
// This don't work
// const map = mapRef.current.leafletElement
// map.flyTo(regionCoord, zoom)
}
return (
<React.Fragment>
<Grid container >
<Grid item xs={10}>
{regionCoord amp;amp; <MapContainer
ref={mapRef}
center={[50,50]}
zoom={zoom}
>
<TileLayer
attribution='amp;copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={regionCoord}>
<Popup>{regionName}</Popup>
</Marker>
</MapContainer>}
</Grid>
<Grid item xs={2}>
<button onClick={handleFlyToClick}>Fly To</button>
</Grid>
</Grid>
</React.Fragment>
)
}
export default Map
Я использую react-leaflet v3
Ответ №1:
Вам нужно использовать компонент, который будет включать вашу кнопку внутри. Чтобы получить экземпляр карты, используйте whenCreated
prop of MapContainer
. Я думаю mapRef
, что это больше не действует в последней версии.
MapContainer:
const [map, setMap] = useState(null);
<MapContainer
center={[50, 50]}
zoom={zoom}
style={{ height: "90vh" }}
whenCreated={setMap}
>
...
</MapContainer>
<FlyToButton /> // use the button here outside of the MapContainer
....
Создайте компонент с кнопкой и ее событием
function FlyToButton() {
const onClick = () => map.flyTo(regionCoord, zoom);
return <button onClick={onClick}>Add marker on click</button>;
}
Комментарии:
1. Изо всех сил пытаясь найти, как получить instace карты (whenCreated={setMap}) спасла мне жизнь. Спасибо
2. Жаль, что это не было в документации!
3. whenCreated, похоже, не существует в react-листовке 4.x
4. Этот ответ был для react-leaflet v.3.x. Это четко указано в вопросе.
5. @kboul разве вы не посчитали бы это дубликатом, если бы кто-то опубликовал тот же точный вопрос для 4.x?
Ответ №2:
вам нужно получить доступ к элементу карты (из компонента карты, который является контейнером, а не MapContainer), это очень простой пример:
export default function MapComponent() {
const [mapCenter,setMapCenter] = useState([13.1538432,30.2154278])
let [zoom,setZoomLevel] = useState(15)
let [tile,setTile] = useState('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png')
let mapRef = useRef();
const fly=()=>{
mapRef.current.leafletElement.flyTo([14,30],15)
}
return (
<>
<button onClick={fly}>Click</button>
<Map center={mapCenter} zoom={zoom} ref={mapRef} style={{width:'100%',height:'100%'}}>
<TileLayer url={tile}/>
</Map>
</>
)
}
Комментарии:
1. я увидел ответ @kboul после того, как опубликовал это, обратите внимание, что я использую react-листовку 2.8.0.
2. Это больше не работает в листовке 3.0. Способ таков, как описано в принятом здесь ответе, используя <MapContainer center={[50, 50]} zoom={zoom} style={{ height: «90vh» }} whenCreated={setMap} >
Ответ №3:
whenCreated
больше не существует в версии 4.0, но есть ref
:
MapContainer:
const [map, setMap] = useState<Map>(null);
<MapContainer
center={[50, 50]}
zoom={zoom}
style={{ height: "90vh" }}
ref={setMap}
>
<div>
... do whatever you want with `map`
</div
</MapContainer>
Ответ №4:
Работает как для 3.x, так и для 4.x:
Другой метод заключается в использовании useMap
перехвата, который существует в 3.x и 4.x. Чтобы использовать его в родительском компоненте, вам просто нужно добавить дочерний компонент, например MapController
, ниже.
const MapController = () => {
const map = useMap();
// do something with map, in a useEffect hook, for example.
return <></>;
};
<MapContainer
center={[50, 50]}
zoom={zoom}
style={{ height: "90vh" }}
>
<MapController />
<div>
... do whatever you want with `map`
</div
</MapContainer>