如何使用 react + redux 在传单 v3 中获取地图属性和处理事件?
How to get map properties and handle events in leaflet v3 with react + redux?
我是 React redux(和 hooks)的新手,我一直在关注 this 一般教程:
我也对使用 react-leaflet 很感兴趣,在撰写本文时它是在使用 hooks 的 v3 上。我已经能够加载包含 latlng 数组的数据以生成标记:
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { Map, MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
import { Icon } from "leaflet";
import "../../css/app.css";
import { useSelector, useDispatch } from "react-redux";
import { getMarkers, selectMarkers } from "../features/markerSlice";
export const LeafMap = () => {
//marker state
const stateMarker = useSelector(state => state.marker);
const dispatch = useDispatch();
useEffect(() => {dispatch(getMarkers());}, [dispatch]);
// map state
const stateMap = useSelector(state => state.map)
if (stateMarker.markers.length > 0) {
return (
<MapContainer center={stateMap.center} zoom={stateMap.zoom} scrollWheelZoom={true}>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{stateMarker.markers.map(el => (
<Marker position={[el.latitude, el.longitude]}/>
))}
</MapContainer>
);
} else {
return (
<MapContainer center={stateMap.center} zoom={stateMap.zoom} scrollWheelZoom={true}>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
);
}
}
目前,我对如何处理点击事件(标记点击)以及访问地图状态(当前边界框、当前缩放级别等)感到很困惑。我遇到错误,例如我无法访问地图状态,除非它在子组件中,或者无法识别 onclick 处理程序等。
我希望最终能够做一些事情,例如根据缩放和边界框动态加载标记,然后单击标记以放大它。这可能是因为我是 React redux 和一般钩子的绝对起点。
我不是在寻找任何人来为我编写代码,但如果有人可以提供有关如何完成这些代码的一般指导,我将不胜感激!
要处理标记点击事件,请使用 eventHandlers
道具并在 Markers
comp 上收听点击事件,如下所示:
const CustomMarkers = () => {
const map = useMap();
return markers.map((el, i) => (
<Marker
key={i}
position={[el.latitude, el.longitude]}
icon={icon}
eventHandlers={{
click: () => {
console.log("marker clicked", el);
console.log(map.getZoom());
}
}}
/>
));
};
您可以像这样导出每个标记元素,并在单击每个标记时使用 useMap
挂钩获取有关地图的信息。
根据缩放级别动态加载标记。一个例子可能是这样的:
你有一个 btn。当您单击它时,您会动态添加一个标记,该标记具有一个事件侦听器以进一步缩放地图。例如,仅当当前地图缩放级别为 6 时才会触发此事件。
function AddMarkerOnClick({ map }) {
const onClick = () => {
console.log(map.getZoom());
if (map?.getZoom() === 6) {
L.marker([39.77, -106.23], { icon })
.addTo(map)
.addEventListener("click", () => map.setZoom(4));
}
};
return <button onClick={onClick}>Add marker on click</button>;
}
...
return (
<>
<AddMarkerOnClick map={map} />
<MapContainer
center={position}
...
</>
)
为了能够获取地图参考,您需要将自定义组件作为子组件置于 MapContainer
之下,或者使用 MapContainer 的 whenCreated
道具获取 map instance
,然后将其传递您的定制版。
示例Demo
在 react-leaflet v3 中,如果你想在另一个应用程序中使用地图及其属性,或者想从另一个组件向地图添加一些东西,你可以使用这个技巧:
class MapComponent extends Component {
constructor(props) {
super(props);
this.mapRef = React.createRef();
}
render() {
return (
<div>
<MapContainer whenCreated={ mapInstance => { this.mapRef.current =mapInstance }}>
</MapContainer>
<AnotherComponent map = {this.mapRef}/>
</div>}
}
class AnotherApp extends React.Component {
//access the map with:
this.props.map
}
我是 React redux(和 hooks)的新手,我一直在关注 this 一般教程:
我也对使用 react-leaflet 很感兴趣,在撰写本文时它是在使用 hooks 的 v3 上。我已经能够加载包含 latlng 数组的数据以生成标记:
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { Map, MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
import { Icon } from "leaflet";
import "../../css/app.css";
import { useSelector, useDispatch } from "react-redux";
import { getMarkers, selectMarkers } from "../features/markerSlice";
export const LeafMap = () => {
//marker state
const stateMarker = useSelector(state => state.marker);
const dispatch = useDispatch();
useEffect(() => {dispatch(getMarkers());}, [dispatch]);
// map state
const stateMap = useSelector(state => state.map)
if (stateMarker.markers.length > 0) {
return (
<MapContainer center={stateMap.center} zoom={stateMap.zoom} scrollWheelZoom={true}>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{stateMarker.markers.map(el => (
<Marker position={[el.latitude, el.longitude]}/>
))}
</MapContainer>
);
} else {
return (
<MapContainer center={stateMap.center} zoom={stateMap.zoom} scrollWheelZoom={true}>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
);
}
}
目前,我对如何处理点击事件(标记点击)以及访问地图状态(当前边界框、当前缩放级别等)感到很困惑。我遇到错误,例如我无法访问地图状态,除非它在子组件中,或者无法识别 onclick 处理程序等。
我希望最终能够做一些事情,例如根据缩放和边界框动态加载标记,然后单击标记以放大它。这可能是因为我是 React redux 和一般钩子的绝对起点。
我不是在寻找任何人来为我编写代码,但如果有人可以提供有关如何完成这些代码的一般指导,我将不胜感激!
要处理标记点击事件,请使用 eventHandlers
道具并在 Markers
comp 上收听点击事件,如下所示:
const CustomMarkers = () => {
const map = useMap();
return markers.map((el, i) => (
<Marker
key={i}
position={[el.latitude, el.longitude]}
icon={icon}
eventHandlers={{
click: () => {
console.log("marker clicked", el);
console.log(map.getZoom());
}
}}
/>
));
};
您可以像这样导出每个标记元素,并在单击每个标记时使用 useMap
挂钩获取有关地图的信息。
根据缩放级别动态加载标记。一个例子可能是这样的: 你有一个 btn。当您单击它时,您会动态添加一个标记,该标记具有一个事件侦听器以进一步缩放地图。例如,仅当当前地图缩放级别为 6 时才会触发此事件。
function AddMarkerOnClick({ map }) {
const onClick = () => {
console.log(map.getZoom());
if (map?.getZoom() === 6) {
L.marker([39.77, -106.23], { icon })
.addTo(map)
.addEventListener("click", () => map.setZoom(4));
}
};
return <button onClick={onClick}>Add marker on click</button>;
}
...
return (
<>
<AddMarkerOnClick map={map} />
<MapContainer
center={position}
...
</>
)
为了能够获取地图参考,您需要将自定义组件作为子组件置于 MapContainer
之下,或者使用 MapContainer 的 whenCreated
道具获取 map instance
,然后将其传递您的定制版。
示例Demo
在 react-leaflet v3 中,如果你想在另一个应用程序中使用地图及其属性,或者想从另一个组件向地图添加一些东西,你可以使用这个技巧:
class MapComponent extends Component {
constructor(props) {
super(props);
this.mapRef = React.createRef();
}
render() {
return (
<div>
<MapContainer whenCreated={ mapInstance => { this.mapRef.current =mapInstance }}>
</MapContainer>
<AnotherComponent map = {this.mapRef}/>
</div>}
}
class AnotherApp extends React.Component {
//access the map with:
this.props.map
}