我有一个表格,其中用户必须指定他的家在 map 上的位置.在这张表格里,我用了React Leaflet张 map .

<Marker>的默认位置为用户的当前位置.我想有一个按钮,每当用户点击它,标记变得可拖动,并可以放置在任何地方的用户设置它.我还在<Popup>中添加了一个提交按钮,当用户点击它时,标记必须是不可拖动的,并且必须更新和保存标记位置才能发送到后端.

以下是我的代码:

const SetViewToCurrentLocation = ({location, setLocation}) => {
    const map = useMap();

    function getGeo() {
        navigator.geolocation.getCurrentPosition( 
            (position) =>  {
                setLocation({
                    lat: position.coords.latitude,
                    lng: position.coords.longitude,
                });
            }, 
            (error) => {
                console.log("--------- ERROR WHILE FETCHING LOCATION ----------- ", error);
            },
            { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000}
            ) ;
    }

    useEffect(() => {
        getGeo();
    }, []);

    useEffect(() => {
        if (location.lat && location.lng) {
            map.setView([location.lat, location.lng]);
        }
    }, [location]);

    return null;
};

const CustomizeMarker = ({location, setLocation}) => {
    const [draggable, setDraggable] = useState(false);
    console.log("*************** THE INPUT LOCATION IS ***************** ", location);
    let lat = location.lat;
    let lng = location.lng;
    const [position, setPosition] = useState({lat, lng});
    console.log("-----------------THE POS VALUE IS ------------------- ", position);
    const markerRef = useRef(null);

    const eventHandlers = useMemo(
        () => ({
            dragend() {
            const marker = markerRef.current
            if (marker != null) {
                console.log("+++++++++++ THE OUTPUT OF getLatLng IS ++++++++++++ ", marker.getLatLng());
                setPosition(marker.getLatLng());
                setDraggable(false);
            }
            },
        }),
        [],
    );

    const toggleDraggable = useCallback(() => {
        setDraggable((d) => !d)
    }, []);

    const saveLocation = () => {
        console.log("HELLO WORLD");
    };


    return (
        <>
            <Marker
                draggable={draggable}
                eventHandlers={eventHandlers}
                position={[position.lat, position.lng]}
                ref={markerRef}>
                <Popup minWidth={90}>
                    <Button onClick={saveLocation}>Submit</Button>
                </Popup>
            </Marker>
            <Button  onClick={toggleDraggable} variant='contained' className='edit-location-button'>Edit Your Location</Button>

        </>
    );
}
const EditHome = () => {
    const [location, setLocation] = useState({});

    return (
        <React.Fragment>
            <Box
                component="form"
                sx={{
                "& .MuiTextField-root": { m: 1, maxWidth: "100%"},
                }}
                noValidate
                autoComplete="off"
                dir="ltr"
            >
                    <form>
                        <div style={{ paddingLeft: "2.5rem" }}>
                            <Grid item xs={12}>
                                <h6 style={{ fontWeight: "bold", paddingRight: "4.9rem", marginTop: "0.8rem" }}>
                                    Specify The Location of Your Home on The Map
                                </h6>
                                <div className='map-container'>
                                    <MapContainer center={[0, 0]} zoom={16} scrollWheelZoom={true}>
                                        <TileLayer
                                            attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                                            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                                        />
                                        <GeoSearchField />
                                        <SetViewToCurrentLocation location={location} setLocation={setLocation}/>
                                        {location.lat && location.lng && (<CustomizeMarker location={location} setLocation={setLocation} />)}
                                    </MapContainer>
                                </div>
                            </Grid>
                         </div>
                    </form>
                </Grid>
            </Box>
        </React.Fragment>
    )
}

export default EditHome;

但我有几个问题.第一个问题是<Button>在 map 中不可见,我想将它设置在 map 的左上角,我已经为它定义了下面的CSS class.

.leaflet-container {
    width: 57rem;
    height: 40rem;
}

.map-container {
    position: relative;
}

.edit-location-button {
    position: absolute;
    top: 10px;
    right: 10px;
}

第二个问题是标记的功能和其位置的更改处理程序.

This is the current output of my implementation: enter image description here I will be grateful for any help.

推荐答案

你已经很接近了.

首先,为了能够看到按钮,在您的css中添加一个zindex值,足够大的应该放在 map 的顶部

.edit-location-button {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10000;
}

其次,您需要使按钮的类型为Button,否则它们看起来像是Submit类型,这会导致页面在每次单击时刷新.它应该类似于material 的用户界面.我是用纯html格式做的.在你的纽扣上加type="button".

   <>
      <Marker
        draggable={draggable}
        eventHandlers={eventHandlers}
        position={[position.lat, position.lng]}
        ref={markerRef}
      >
        <Popup minWidth={90}>
          <button type="button" onClick={saveLocation}>
            Submit
          </button>
        </Popup>
      </Marker>
      <button
        type="button"
        onClick={toggleDraggable}
        className="edit-location-button"
      >
        Edit Your Location
      </button>
   </>

功能看起来还行,而且还能用.唯一的问题是,您不必在Marker组件中添加编辑位置按钮,因为它们是不相关的.我把它放在外面你已经有的碎片下面了.此外,要在单击提交时获得坐标,您需要调用

 const saveLocation = () => {
     if (markerRef.current)
      console.log(
        "+++++++++++ THE OUTPUT OF getLatLng IS ++++++++++++ ",
        markerRef.current.getLatLng()
      );
  };

而不是将标记记录在拖动回调中.

你可以在demo分中看到结果.

Javascript相关问答推荐

Vue-Router渲染组件但不更改网址

除了在Angular 16中使用快照之外,什么是可行且更灵活的替代方案?

如何访问Json返回的ASP.NET Core 6中的导航图像属性

从PWA中的内部存储读取文件

如何在Connect 4游戏中 for each 玩家使用位板寻找7形状?

Next.js(react)使用moment或不使用日期和时间格式

如何从URL获取令牌?

如何在JavaScript文件中使用Json文件

如何在输入元素中附加一个属性为checkbox?

如何使用子字符串在数组中搜索重复项

S文本内容和值不必要的不同

Angular 订阅部分相互依赖并返回数组多个异步Http调用

如何在每次单击按钮时重新加载HighChart/设置HighChart动画?

第二次更新文本输入字段后,Reaction崩溃

Puppeteer上每页的useProxy返回的不是函数/构造函数

MarkLogic-earch.suggest不返回任何值

为什么我的按钮没有从&q;1更改为&q;X&q;?

匹配一个或多个可选重复的特定模式

ngOnChanges仅在第二次调用时才触发

如何将字符串拆分成单词并跟踪每个单词的索引(在原始字符串中)?