首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建一个按钮来启用/禁用javascript中的传单缩放和pan?

如何创建一个按钮来启用/禁用javascript中的传单缩放和pan?
EN

Stack Overflow用户
提问于 2022-09-05 15:37:20
回答 1查看 212关注 0票数 1

正如标题所述,我正在搜索如何创建一个按钮来启用/禁用javascript react中的传单缩放和pan。实际上创建一个按钮是很好的,但是在我的地图上得到我想要的效果却不是。

我正在致力于一个反应项目,并试图实现一个传单地图之间的“编辑”模式和“静态”模式之间的小块。编辑将使用传单绘制命令显示地图,并允许用户缩放和平移。静态将隐藏整个绘图界面,不允许缩放和平移,实际上是将地图转换为固定图像。

我已经实现了一个传单地图和一个按钮,它向组件中的绘图对象添加/删除一个“隐藏”类。现在,我正试图在同一按钮中添加一些内容,以便在活动和非活动之间切换缩放和平移。

我手动更改了代码中的属性"scrollWheelZoom“和”拖动“,并获得了所需的效果,因此我想我现在需要用按钮来更改它们。我尝试使用querySelector来选择我的地图并更改属性,但是它没有工作(我猜映射已经呈现,不会改变)。然后,我尝试将参数值设置为等于作为按钮开关的布尔状态的参数值,但得到了相同的结果。我在网上看到的大多数例子都使用了一种完全不同的方法来创建地图,如果我能理解的话,那是因为除了传单之外,它们并没有使用react。

是否有一种方法可以更新映射的这些属性,或者以另一种方式创建映射,从而使我能够更容易地更新属性?

下面是该代码的当前版本。使用查询方法更新"scrollWheelZoom“,用状态方法”拖动“。

代码语言:javascript
复制
//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='&copy; <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>
    )
}

这是我在这里的第一个问题,我希望在发布之前我没有犯任何大的错误。提前谢谢你的帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-07 08:01:48

正如我在评论中所写的,您不应该将香草js与react结合使用,因为两者都负责更改状态,这将导致意外的错误和行为。

因此,您需要达到的目标是首先禁用所有映射交互,然后启用它们,就像您可能认为的那样。在开始时,您可以很容易地实现这一点,因为您将属性作为道具传递,并且创建一个状态变量在编辑按钮显示之间切换。唯一的例外是首先需要通过useEffect禁用缩放控件。但是,为了动态地启用映射交互,您需要通过映射引用进行映射交互,因为mapcontainer's道具是不可变的,这意味着您不能通过状态更改它们。一旦他们创造了,他们就不能改变。你有两种选择。在按钮onClick事件中直接更改它们,或者创建一个自定义的leaflet组件,当编辑模式被启用或为真时,该组件将被呈现。

代码语言:javascript
复制
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>
</>

您可以进一步简化onClick函数。检查演示

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73611765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档