-1

我正在使用leaflet.gesturehandling和react 来支持两个手指滚动和带有传单的ctrl+scroll-wheel。

使用演示测试此功能,我发现在桌面上一切正常。然而,在移动设备上,我发现这种行为非常古怪。尝试使用两个手指手势时页面将滚动。缩放与平移混合在一起,这简直是不可预测的。我已经包含了我认为遵循作者指导的实现。

在此处输入图像描述

我想知道,我在这里做错了吗?当两根手指与传单容器接触时,我是否需要禁用页面滚动?

有没有人遇到过这个?

import React from "react"
import PropTypes from "prop-types"
import { MapContainer, TileLayer, Marker, GeoJSON } from "react-leaflet"
import "./leafletMap.css"
import * as L from "leaflet";
import { GestureHandling } from "leaflet-gesture-handling";

import "leaflet/dist/leaflet.css";
import "leaflet-gesture-handling/dist/leaflet-gesture-handling.css";

const proj4 = typeof window !== `undefined` ? require("proj4leaflet") : null

class LeafletMap extends React.Component {
  static propTypes = {
    bounds: PropTypes.array,
    startMarker: PropTypes.array,
    endMarker: PropTypes.array,
    route: PropTypes.object,
  }

  static defaultProps = {
    position: [51, -1],
    zoom: 13,
    markerText: "",
  }

  render() {
    /* Required by gatsby build, works fine witohut in develop since window is defined browser? */
    if (typeof window !== "undefined") {
      // Setup the EPSG:27700 (British National Grid) projection.
      var crs = new proj4.CRS(
        "EPSG:27700",
        "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs",
        {
          resolutions: [
            896.0,
            448.0,
            224.0,
            112.0,
            56.0,
            28.0,
            14.0,
            7.0,
            3.5,
            1.75,
          ],
          origin: [-238375.0, 1376256.0],
        }
      )

      // Initialize the map.
      var mapOptions = {
        crs: crs,
        minZoom: 0,
        maxZoom: 9,
        attributionControl: false,
        //gestureHandling: true
      }

      L.Map.addInitHook("addHandler", "gestureHandling", GestureHandling);

      return (
        
        <MapContainer bounds={this.props.bounds} {...mapOptions}>
          <TileLayer
            attribution='&copy; &copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            url="https://api.os.uk/maps/raster/v1/zxy/Leisure_27700/{z}/{x}/{y}.png?key=4O65KRx7pDwdZq98W173UDKX1OSUNOAq"
          />

          <GeoJSON data={this.props.route} />
          <Marker position={this.props.startMarker} />
          <Marker position={this.props.endMarker} />
        </MapContainer>
      )
    }
    return null
  }
}

export default LeafletMap

4

2 回答 2

1

我在使用 react-leaflet 实现传单手势处理时遇到了一些困难,但这是一个工作示例:

import React, { ReactElement, useEffect, useState } from "react";
import {
  MapContainer,
  Marker,
  TileLayer,
  useMap,
  useMapEvents,
} from "react-leaflet";
import {
  LatLngBounds,
  latLngBounds,
  LatLngExpression,
  LeafletEvent,
  LeafletMouseEvent,
} from "leaflet";
import { getIcon, MarkerClustor } from "@components/map/MarkerClusterGroup";
import { GestureHandling } from "leaflet-gesture-handling";
import "leaflet/dist/leaflet.css";
import "leaflet-gesture-handling/dist/leaflet-gesture-handling.css";

type MarkerType = "current" | "pg" | "pgContactList";

export interface MarkerProps {
  id: string;
  isCurrentLocation?: boolean;
  label?: ReactElement;
  position: LatLngExpression;
  type?: MarkerType;
}

export interface RegionProps {
  id: string;
  name: string;
  coords: LatLngExpression[][] | LatLngExpression[][][];
  bounds?: LatLngBounds;
}

interface MapLeafletProps {
  markers?: MarkerProps[];
  markersContactList?: MarkerProps[];
  markerCurrentLocationId?: string;
  center?: LatLngExpression;
  scrollWheelZoom?: boolean;
  autoCenter?: boolean;
  className?: string;
  onMapZoomEnd: (e: LeafletEvent) => void;
  onMapDragEnd: (e: LeafletEvent) => void;
  onMouseUp: (e: LeafletMouseEvent) => void;
  onClickMarker?: (id: string) => void;
  updateBounds?: boolean;
  zoom?: number;
}

const MapLeaflet = (props: MapLeafletProps): ReactElement => {
  const {
    markers = [],
    markersContactList = [],
    markerCurrentLocationId,
    center = [46.7111, 1.7191],
    className,
    onMapZoomEnd,
    onMapDragEnd,
    onClickMarker,
    updateBounds = false,
    zoom = 7,
  } = props;

  const [bounds, setBounds] = useState<LatLngBounds>();
  const[init, setInit] = useState<boolean>(true);


  const LocationMarker = () => {
    const map = useMapEvents({
      locationfound(e) {
        map.flyTo(e.latlng, map.getZoom());
      },
      zoomend(e) {
        onMapZoomEnd(e);
      },
      dragend(e) {
        onMapDragEnd(e);
      },
    });

    return null;
  };

  const BoundsSetter = () => {
    const map = useMap();
    console.log("Set new bounds");
    bounds && map.fitBounds(bounds);
    return null;
  };

  const GestureHandlingSetter = () => {
    /* eslint-disable */
    const map = useMap() as any;
    map.gestureHandling.enable();
    map.addHandler("gestureHandling", GestureHandling);
    setInit(false);
    /* eslint-enable */
    return null;
  };

  useEffect(() => {
    const gpMarkers = markers.filter((marker) => !marker.isCurrentLocation);
    setBounds(
      gpMarkers.length > 0
        ? latLngBounds(
            gpMarkers.map(
              (marker: MarkerProps): LatLngExpression => marker.position,
            ),
          ).pad(0.05)
        : undefined,
    );
  }, [markers]);

  const markerClusterComponent = React.useMemo(() => {
    return (
      <MarkerClustor
        markers={markers.filter((marker) => !marker.isCurrentLocation)}
        onClickMarker={onClickMarker}
        markerCurrentLocationId={markerCurrentLocationId}
      />
    );
  }, [markers, onClickMarker, markerCurrentLocationId]);

  return (
    <MapContainer
      id="map-id"
      center={center}
      zoom={zoom}
      className={className}
      scrollWheelZoom={false}
      doubleClickZoom={true}
      minZoom={2}
      preferCanvas={false}
      whenCreated={() => console.log("Map Created")}
      whenReady={() => console.log("Map Ready")}
    >
      {init && <GestureHandlingSetter />}
      <TileLayer url="https://{s}.tile.osm.org/{z}/{x}/{y}.png" noWrap={true} />
      {markerClusterComponent}
      {markersContactList.map((marker: MarkerProps, index) => (
        <Marker
          key={`marker_contact_list_${index}`}
          position={marker.position}
          icon={getIcon(marker.type, marker.id, markerCurrentLocationId)}
          eventHandlers={{
            click: () => {
              onClickMarker && onClickMarker(marker.id);
            },
          }}
        />
      ))}
      <LocationMarker />
      {updateBounds && <BoundsSetter />}
    </MapContainer>
  );
};

export default MapLeaflet;
于 2021-10-21T10:43:09.487 回答
1

不确定您是否已设置为使用 leaflet.gestureHandling 进行双指 scolling 解决方案,但在这里,https: //stackoverflow.com/a/41631385/8543190是另一种解决方案,如果您需要使用传单交互选项https 的替代方案: //leafletjs.com/reference-1.4.0.html#map-closepopuponclick

于 2021-05-10T05:53:59.773 回答