React-Leaflet实现点击Marker动态改变地图中心位置
问题
我用Leaflet构建了一张地图,包含3个点位数据,每个点位都创建了带弹窗的Marker。当前地图中心是硬编码值,希望实现点击每个Marker时动态调整地图中心的功能,请问该如何实现?现有代码如下:
import L from "leaflet"; import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet"; import parse from "html-react-parser"; import logoFFB from "@/images/ffb.svg"; const Map = () => { const coordinates = [ { id: 1, popup: ` <div> <a href="#" target="_blank" class="cursor-pointer"> <img class="max-w-[70px] my-5" src=${logoFFB} alt="Friends For Brands" /> </a> <h4 class="font-bold text-lg text-red-500">Lorem Ipsum</h4> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean cursus ligula sapien, dignissim pretium nisl pharetra id.</p> <p>Maecenas venenatis blandit risus, eu faucibus lorem vehicula at. Aliquam finibus magna tellus, eu pharetra nibh vehicula sed.</p> </div> `, lat: 51.91662, lng: 4.4727, }, { id: 2, popup: ` <div> <a href="https://mediamarkt.nl" target="_blank" class="cursor-pointer"> <img class="max-w-[100px] my-5" src="https://upload.wikimedia.org/wikipedia/commons/f/f0/Media_Markt_logo.svg" alt="Mediamarkt" /> </a> <h4 class="font-bold text-lg text-red-500">Lorem Ipsum</h4> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean cursus ligula sapien, dignissim pretium nisl pharetra id.</p> <p>Maecenas venenatis blandit risus, eu faucibus lorem vehicula at. Aliquam finibus magna tellus, eu pharetra nibh vehicula sed.</p> </div> `, lat: 51.92019, lng: 4.48006, }, { id: 3, popup: ` <div> <a href="https://www.erasmusmc.nl" target="_blank" class="cursor-pointer"> <img class="max-w-[120px] my-5" src="https://www.erasmusmc.nl/-/media/erasmusmc/images/_platform/logos/full-colour-svg-sophia-kinderziekenhuis-sub-brand-3.svg?la=nl-NL&hash=738FF636E5026AE3B56EE1D79492BB50" alt="MC Sophia" /> </a> <h4 class="font-bold text-lg text-red-500">Lorem Ipsum</h4> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean cursus ligula sapien, dignissim pretium nisl pharetra id.</p> <p>Maecenas venenatis blandit risus, eu faucibus lorem vehicula at. Aliquam finibus magna tellus, eu pharetra nibh vehicula sed.</p> </div> `, lat: 51.911781, lng: 4.4696, }, ]; const CUSTOM_MARKER = `data:image/svg+xml;utf8,${encodeURIComponent(`<?xml version="1.0" encoding="iso-8859-1"?> <svg width="36px" height="36px" viewBox="-4 0 36 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g id="Vivid.JS" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Vivid-Icons" transform="translate(-125.000000, -643.000000)"> <g id="Icons" transform="translate(37.000000, 169.000000)"> <g id="map-marker" transform="translate(78.000000, 468.000000)"> <g transform="translate(10.000000, 6.000000)"> <path d="M14,0 C21.732,0 28,5.641 28,12.6 C28,23.963 14,36 14,36 C14,36 0,24.064 0,12.6 C0,5.641 6.268,0 14,0 Z" id="Shape" fill="#FF6E6E"></path> <circle id="Oval" fill="#0C0058" fill-rule="nonzero" cx="14" cy="14" r="7"></circle> </g> </g> </g> </g> </g> </svg> `)}`; return ( <MapContainer id="map" center={[51.91662, 4.4727]} zoom={16} scrollWheelZoom={false} > <TileLayer attribution="© Friends For Brands" url="https://tiles.stadiamaps.com/tiles/outdoors/{z}/{x}/{y}{r}.png" /> {coordinates.map((coordinate) => ( <Marker key={coordinate.id} position={[coordinate.lat, coordinate.lng]} icon={L.icon({ iconUrl: CUSTOM_MARKER, iconSize: [35, 35], iconAnchor: [12, 12], popupAnchor: [0, 0], })} > <Popup className="text-md">{parse(coordinate.popup)}</Popup> </Marker> ))} </MapContainer> ); }; export default Map;
解决方案
要实现点击Marker时动态调整地图中心,只需通过React状态管理地图中心,并给Marker绑定点击事件更新状态即可,具体步骤:
- 引入
useState钩子,初始化地图中心状态为原硬编码值 - 给每个Marker添加
onClick事件,触发时将状态更新为当前Marker的坐标 - 将
MapContainer的center属性绑定到状态变量
修改后的完整代码:
import L from "leaflet"; import { useState } from "react"; import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet"; import parse from "html-react-parser"; import logoFFB from "@/images/ffb.svg"; const Map = () => { // 初始化地图中心状态 const [mapCenter, setMapCenter] = useState([51.91662, 4.4727]); const coordinates = [ { id: 1, popup: ` <div> <a href="#" target="_blank" class="cursor-pointer"> <img class="max-w-[70px] my-5" src=${logoFFB} alt="Friends For Brands" /> </a> <h4 class="font-bold text-lg text-red-500">Lorem Ipsum</h4> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean cursus ligula sapien, dignissim pretium nisl pharetra id.</p> <p>Maecenas venenatis blandit risus, eu faucibus lorem vehicula at. Aliquam finibus magna tellus, eu pharetra nibh vehicula sed.</p> </div> `, lat: 51.91662, lng: 4.4727, }, { id: 2, popup: ` <div> <a href="https://mediamarkt.nl" target="_blank" class="cursor-pointer"> <img class="max-w-[100px] my-5" src="https://upload.wikimedia.org/wikipedia/commons/f/f0/Media_Markt_logo.svg" alt="Mediamarkt" /> </a> <h4 class="font-bold text-lg text-red-500">Lorem Ipsum</h4> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean cursus ligula sapien, dignissim pretium nisl pharetra id.</p> <p>Maecenas venenatis blandit risus, eu faucibus lorem vehicula at. Aliquam finibus magna tellus, eu pharetra nibh vehicula sed.</p> </div> `, lat: 51.92019, lng: 4.48006, }, { id: 3, popup: ` <div> <a href="https://www.erasmusmc.nl" target="_blank" class="cursor-pointer"> <img class="max-w-[120px] my-5" src="https://www.erasmusmc.nl/-/media/erasmusmc/images/_platform/logos/full-colour-svg-sophia-kinderziekenhuis-sub-brand-3.svg?la=nl-NL&hash=738FF636E5026AE3B56EE1D79492BB50" alt="MC Sophia" /> </a> <h4 class="font-bold text-lg text-red-500">Lorem Ipsum</h4> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean cursus ligula sapien, dignissim pretium nisl pharetra id.</p> <p>Maecenas venenatis blandit risus, eu faucibus lorem vehicula at. Aliquam finibus magna tellus, eu pharetra nibh vehicula sed.</p> </div> `, lat: 51.911781, lng: 4.4696, }, ]; const CUSTOM_MARKER = `data:image/svg+xml;utf8,${encodeURIComponent(`<?xml version="1.0" encoding="iso-8859-1"?> <svg width="36px" height="36px" viewBox="-4 0 36 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g id="Vivid.JS" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Vivid-Icons" transform="translate(-125.000000, -643.000000)"> <g id="Icons" transform="translate(37.000000, 169.000000)"> <g id="map-marker" transform="translate(78.000000, 468.000000)"> <g transform="translate(10.000000, 6.000000)"> <path d="M14,0 C21.732,0 28,5.641 28,12.6 C28,23.963 14,36 14,36 C14,36 0,24.064 0,12.6 C0,5.641 6.268,0 14,0 Z" id="Shape" fill="#FF6E6E"></path> <circle id="Oval" fill="#0C0058" fill-rule="nonzero" cx="14" cy="14" r="7"></circle> </g> </g> </g> </g> </g> </svg> `)}`; return ( <MapContainer id="map" center={mapCenter} zoom={16} scrollWheelZoom={false} > <TileLayer attribution="© Friends For Brands" url="https://tiles.stadiamaps.com/tiles/outdoors/{z}/{x}/{y}{r}.png" /> {coordinates.map((coordinate) => ( <Marker key={coordinate.id} position={[coordinate.lat, coordinate.lng]} icon={L.icon({ iconUrl: CUSTOM_MARKER, iconSize: [35, 35], iconAnchor: [12, 12], popupAnchor: [0, 0], })} onClick={() => setMapCenter([coordinate.lat, coordinate.lng])} > <Popup className="text-md">{parse(coordinate.popup)}</Popup> </Marker> ))} </MapContainer> ); }; export default Map;
内容的提问来源于stack exchange,提问作者Galanthus
相关产品推荐
相关产品推荐

