[英]How to create a button to enable/disable zoom and pan for leaflet in javascript react?
正如标题所说,我正在搜索如何创建一个按钮来启用/禁用 javascript 反应中 leaflet 的缩放和平移。 实际上创建一个按钮很好,但是在我的 map 上获得我想要的效果不是。
我正在研究一个反应项目并尝试实现一个在“编辑”模式和“静态”模式之间切换的 leaflet map。 编辑将显示带有传单绘制命令的 map,并允许用户缩放和平移。 Static 将隐藏整个绘图界面并禁止缩放和平移,实际上将 map 变为固定图像。
我已经实现了一个 leaflet map 和一个添加/删除“隐藏” class 到绘图 ZA8Z6FDE6331C4BEB666 组件的按钮。 现在我正在尝试向同一个按钮添加一些东西,以在活动和非活动之间切换缩放和平移。
我在代码中手动更改了属性“scrollWheelZoom”和“拖动”并获得了所需的效果,所以我想我现在需要使用按钮更改它们。 我尝试对 select 我的 map 使用 querySelector 并更改属性,但它没有用(我猜 map 已经呈现并且不会更改)。 然后我尝试将参数值设置为等于我用作按钮开关的 boolean state,但我得到了相同的结果。 我在 web 上看到的大多数示例都使用完全不同的方式来创建 map,如果我理解得很好,那是因为除了 leaflet 之外,它们还没有使用 react。
有没有办法更新我的 map 的这些属性,或者以另一种方式创建 map,让我更轻松地更新属性?
这是代码的当前版本。 “scrollWheelZoom”使用查询方法更新,“拖动”使用 state 方法。
//css imports
import './Map.css';
import 'leaflet/dist/leaflet.css';
import 'leaflet-draw/dist/leaflet.draw.css';
//library imports
import React, { useRef, useEffect, useState } from 'react';
import { MapContainer, TileLayer, FeatureGroup } from 'react-leaflet';
import { EditControl } from 'react-leaflet-draw'
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import L from 'leaflet';
//solution to the missing icon phenomenon in draw
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
//component proper
export default function Map(props) {
const [map, setMap] = useState(null) //state that will contain the map object
let [editState, setEditState] = useState(true); // state to toggle the edit buttons
//draw object that contains parameters for the drawing functions
let drawObject = useRef({
circlemarker: false
});
//handler for the edit button to hide/display the drawing tools
function editHandler(e) {
const $plc = e.target.closest('.placeholders');//select placeholder
const $editObjectDraw = $plc.querySelector('.leaflet-draw');//select target object
const $editObjectMap = $plc.querySelector('.mapContainer');
if (editState) {
$editObjectDraw.classList.add('visually-hidden');//update visual state
$editObjectMap.scrollWheelZoom = editState;
} else {
$editObjectDraw.classList.remove('visually-hidden');//update visual state
$editObjectMap.scrollWheelZoom = editState;
}
setEditState(!editState); //reverse boolean state to go from add to remove
}
return (
<div>
<MapContainer className="mapContainer" center={[45.5053, -73.6138]} zoom={1} scrollWheelZoom={true} dragging={editState} minZoom={0} maxZoom={18} ref={setMap}>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<FeatureGroup>
<EditControl
className='drawControl'
position='topright'
onEdited={_onChange}
onCreated={_onChange}
onDeleted={_onChange}
onMounted={_onChange}
onEditStart={_onChange}
onEditStop={_onChange}
onDeleteStart={_onChange}
onDeleteStop={_onChange}
draw={drawObject.current}
/>
</FeatureGroup>
</MapContainer>
<button className="mapControl" onClick={editHandler}>
<EditOutlinedIcon style={{ fill: "#FCF0E5" }} />
<span>Edit</span>
</button>
</div>
)
}
这是我在这里的第一个问题,我希望在发布之前我没有犯任何大错误。 预先感谢您的帮助。
正如我在评论中所写的那样,您不应将 vanilla js 与 react 结合使用,因为两者都负责更改 state,这将导致意外的错误和行为。
因此,您需要先禁用所有 map 交互,然后按照您的想法启用它们。 一开始您可以轻松实现这一点,因为您将属性作为道具传递并创建 state 变量以在编辑按钮显示之间切换。 唯一的例外是首先需要通过useEffect
禁用的缩放控件。 但是为了动态启用 map 交互,您需要通过 map 参考来完成它,因为mapcontainer's
道具是不可变的,这意味着您不能通过 state 更改它们。 一旦创建,就无法更改。 你有两个选择来做到这一点。 直接在按钮onChange
事件中更改它们,或者创建一个自定义的 react-leaflet 组件,该组件将在启用编辑模式或为 true 时呈现。
export default function Map() {
const [map, setMap] = useState(null); //state that will contain the map object
let [editMode, setEditMode] = useState(false); // state to toggle the edit buttons
useEffect(() => {
if (map) map.zoomControl.disable();
}, [map]);
const handleClick = () => {
if (!editMode) {
map.touchZoom.enable();
map.doubleClickZoom.enable();
map.scrollWheelZoom.enable();
map.keyboard.enable();
map.zoomControl.enable();
map.dragging.enable();
} else {
map.touchZoom.disable();
map.doubleClickZoom.disable();
map.scrollWheelZoom.disable();
map.keyboard.disable();
map.zoomControl.disable();
map.dragging.disable();
}
setEditMode((prevState) => !prevState);
};
<MapContainer
className="mapContainer"
center={[45.5053, -73.6138]}
zoom={1}
style={{ height: "90vh" }}
minZoom={0}
maxZoom={18}
zoomSnap={false}
ref={setMap}
scrollWheelZoom={false}
dragging={false}>
...
{editMode && (
<FeatureGroup>
<EditControl
onEdited={() => {}}
onCreated={() => {}}
onDeleted={() => {}}
draw={{ rectangle: false }}
/>
</FeatureGroup>
)}
</MapContainer>
<button className="mapControl" onClick={handleClick}>
<EditOutlinedIcon />
<span>{!editMode ? "Static" : "Edit"} mode</span>
</button>
</>
您可以进一步简化onChange
function。 检查演示
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.