簡體   English   中英

React/Material-UI Slider/Leafet stopEventPropagation

[英]React/Material-UI Slider/Leafet stopEventPropagation

我正在嘗試使用 react 創建帶有 material-ui 滑塊的傳單地圖控件。 出於某種原因,當我拖動滑塊時,它也會拖動地圖。 當我嘗試禁用控件上的單擊/鼠標移動傳播時,我無法再滑動滑塊。

https://codesandbox.io/s/ecstatic-taussig-iv8rj?file=/src/App.tsx

import * as React from "react";
import ReactDOM from "react-dom";
import L from "leaflet";
import { Slider } from "@material-ui/core";

function useMap(): [React.RefObject<HTMLDivElement>, L.Map | null] {
  const mapRef = React.useRef<HTMLDivElement>(null);

  const [map, setMap] = React.useState<L.Map>(null);

  React.useEffect(() => {
    if (!map && mapRef.current) {
      const newMap = new L.Map(mapRef.current, {
        center: [38.810820900566156, -95.54946899414064],
        zoom: 5
      });
      L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(
        newMap
      );
      setMap(newMap);
    }
  }, [map]);

  return [mapRef, map];
}

function useLeafletWidget(
  map: L.Map | null,
  component: React.ReactElement | null
) {
  const containerRef = React.useRef(document.createElement("div"));
  React.useEffect(() => {
    if (map) {
      const Control = L.Control.extend({
        onAdd() {
          // L.DomEvent.disableClickPropagation(containerRef.current);

          // L.DomEvent.on(containerRef.current, "mousemove", (event) => {
          //   event.stopPropagation();
          // });
          return containerRef.current;
        }
      });
      const control = new Control({
        position: "topleft"
      });
      map.addControl(control);
      return () => {
        map.removeControl(control);
      };
    }
  }, [map]);

  React.useEffect(() => {
    if (component) {
      const container = containerRef.current;
      ReactDOM.render(component, container);
    }
  }, [component]);

  React.useEffect(() => {
    const container = containerRef.current;
    return () => {
      ReactDOM.unmountComponentAtNode(container);
    };
  }, [containerRef]);
}

function useSliderWidget(map: L.Map | null) {
  const widget = React.useMemo(
    () => (
      <div style={{ backgroundColor: "white", padding: 10, width: 150 }}>
        Slider: <Slider />
      </div>
    ),
    []
  );

  useLeafletWidget(map, widget);
}

export const App: React.FC = () => {
  const [mapRef, map] = useMap();

  useSliderWidget(map);

  return (
    <>
      <link
        rel="stylesheet"
        href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
        integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
        crossOrigin=""
      />
      <div ref={mapRef} style={{ flexGrow: 1 }}></div>
    </>
  );
};

您可以在移動或鼠標懸停在滑塊上時添加map.dragging.disable()和后來的map.dragging.enable()

根據 Falke 的回答,我實現了一個鈎子,用於在與地圖頂部的元素交互時禁用地圖拖動和滾動傳播。

import L from 'leaflet'
import { useEffect } from 'react'
import { useMap } from 'react-leaflet'

export const useDisablePropagationInMap = ({
  ref,
}: {
  ref: React.MutableRefObject<HTMLElement | null>
}) => {
  const map = useMap()

  useEffect(() => {
    if (!ref.current) return
    L.DomEvent.disableScrollPropagation(ref.current)
    ref.current.onmouseenter = e => map.dragging.disable()
    ref.current.onmouseleave = e => map.dragging.enable()

    return () => {
      map.dragging.enable()
    }
  }, [ref])
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM