Используя React, Leaflet, leaflet-pixi-overlay, всплывающее окно с маркером закрывается сразу после нажатия - PullRequest
0 голосов
/ 10 марта 2020

Я работаю над картой листовки, под React. Из соображений производительности мне пришлось использовать PixiOverlay для рисования моих маркеров (https://github.com/manubb/Leaflet.PixiOverlay). Я столкнулся с проблемой всплывающих окон, хотя. С помощью следующего кода:

  • событие нажатия маркера правильно запускается при нажатии на маркер
  • , если карта перетаскивается, когда маркер щелкается и отпускается, всплывающее окно открывается очень хорошо
  • НО с помощью одного «чистого» щелчка событие popupclose запускается сразу

Мой гибридный подход (response-leaflet, PixiOverlay) до сих пор работал нормально, но я могу » t обойти эту проблему.

Следующий код упрощен, некоторые элементы взяты из-под контроля React для упрощения кода теста:

import { Map, TileLayer } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import { Paper } from '@material-ui/core';

import * as PIXI from 'pixi.js';
import 'leaflet-pixi-overlay';
import L from 'leaflet';

const pixiMarkerContainer = new PIXI.Container();
let markerTextures = {};

const testPopup = L.popup({ autoPan: false, pane: 'popupPane' });

const markerOverlay = L.pixiOverlay((utils) => {
  const map = utils.getMap();
  const scale = utils.getScale();
  const renderer = utils.getRenderer();
  const container = utils.getContainer();

  if (map && (Object.keys(markerTextures).length !== 0)) {
    if (container.children.length) container.removeChildren();

    const newMarker = new PIXI.Sprite(markerTextures.default);
    const newMarkerPoint = utils.latLngToLayerPoint([50.63, 13.047]);
    newMarker.x = newMarkerPoint.x;
    newMarker.y = newMarkerPoint.y;

    container.addChild(newMarker);
    newMarker.anchor.set(0.5, 1);
    newMarker.scale.set(1 / scale);
    newMarker.interactive = true;
    newMarker.buttonMode = true;

    newMarker.click = () => {
      testPopup
        .setLatLng([50.63, 13.047])
        .setContent('<b>Test</b>');
      console.log('Open popup');
      map.openPopup(testPopup);
    };

    map.on('popupclose', () => { console.log('Close popup'); });

    renderer.render(container);
  }
},
pixiMarkerContainer);

function PixiMap() {
  const [markerTexturesLoaded, setMarkerTexturesLoaded] = useState(false);
  const [mapReady, setMapReady] = useState(false);
  const mapRef = useRef(null);

  useEffect(() => {
    if (Object.keys(markerTextures).length === 0) {
      const loader = new PIXI.Loader();
      loader.add('default', 'https://manubb.github.io/Leaflet.PixiOverlay/img/marker-icon.png');
      loader.load((thisLoader, resources) => {
        markerTextures = { default: resources.default.texture };
        setMarkerTexturesLoaded(true);
      });
    }
  }, []);

  useEffect(() => {
    if (mapReady && markerTexturesLoaded) {
      const map = mapRef.current.leafletElement;
      markerOverlay.addTo(map);
      markerOverlay.redraw();
    }
  }, [mapReady, markerTexturesLoaded]);

  return (
    <Paper
      style={{ flexGrow: 1, height: '100%' }}
    >
      <Map
        preferCanvas
        ref={mapRef}
        style={{ height: '100%' }}
        center={[50.63, 13.047]}
        zoom={12}
        minZoom={3}
        maxZoom={18}
        whenReady={() => { setMapReady(true); }}
        onClick={() => { console.log('map click'); }}
      >
        <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?" />
      </Map>
    </Paper>
  );
}

export default PixiMap;

Есть предложения? Спасибо.


Редактировать: Похоже, что маркер И карта обрабатывают событие click (добавлена ​​регистрация кликов карты в исходном коде). Я хочу, чтобы карта обрабатывала щелчки (которые закрывают всплывающие окна), но не тогда, когда щелчок уже обработан маркером ...


Edit # 2: Я попытался добавить следующее в обработчике кликов маркера:

event.stopPropagation();
event.data.originalEvent.stopPropagation();

Но это абсолютно ничего не делает ... Похоже, это основная проблема c PIXI?

1 Ответ

0 голосов
/ 12 марта 2020

На данный момент я не вижу «чистого» способа остановить распространение события. У меня есть решение:

  • отключить автоматическое закрытие всплывающего окна при нажатии на карту
  • определить, совпадает ли щелчок карты с маркером; закройте всплывающее окно, когда оно не

Объявите всплывающее окно с помощью следующего параметра:

const testPopup = L.popup({
  autoPan: false,
  pane: 'popupPane',
  closeOnClick: false,    // : disable the automatic close
});

В обработчике щелчков маркера запишите позицию этого щелчка:

    newMarker.click = (event) => {
      // Set aside the click position:
      lastMarkerClickPosition = { ...event.data.global };
      testPopup
        .setLatLng([50.63, 13.047])
        .setContent('<b>Test</b>');
      setPopupParams({ text: 'test' });
      map.openPopup(testPopup);
    };

Добавьте обработчик щелчка карты, при необходимости закройте всплывающее окно:

    map.on('click', (event) => {
      // Find click position
      const clickPixiPoint = new PIXI.Point();
      interaction.mapPositionToPoint(
        clickPixiPoint,
        event.originalEvent.clientX,
        event.originalEvent.clientY,
      );

      if (
        (clickPixiPoint.x !== lastMarkerClickPosition.x)
      || (clickPixiPoint.y !== lastMarkerClickPosition.y)
      ) {
        map.closePopup();
      }
    });

Это несколько грязно, так как предполагает, что событие щелчка маркера обрабатывается первым ...

...