2016-10-20 2 views
1

Я пытаюсь написать специальный обработчик событий для CTRL + щелчок в листе. Моя проблема заключается в том, что местоположение клика, данное картой, отличается от местоположения щелчка в обработчике событий, например. LatLng(51.49174, -0.11639) с карты клик будет LatLng(51.50938, -0.126) в обработчике. Точки щелчка точно совпадают, если карта является единственной вещью на странице. Добавление некоторых других элементов div над картой (например, заголовок <h1>) делает клики не соответствующими. Панорамирование карты также делает расположение кликов не совпадающим.Как получить местоположение клика от пользовательского обработчика событий Листовка

Мне интересно, правильно ли я подключил свой L.DomEvent.on(). После Leaflet Handlers tutorial мой код выглядит

L.CtrlClickHandler = L.Handler.extend({ 
    addHooks: function() { 
    L.DomEvent.on(document, 'click', this._captureClick, this); 
    }, 

    removeHooks: function() { 
    L.DomEvent.off(document, 'click', this._captureClick, this); 
    }, 

    _captureClick: function(event) { 
    if (event.ctrlKey) { 
     console.log('control click registered at layer ' 
     + map.layerPointToLatLng(new L.point(event.layerX, event.layerY))); 
    } 
    } 
}); 

// add this to all maps 
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler); 

Вот live example on JSFiddle.

Я использую Leaflet 0.7.7 из-за некоторых других зависимостей в моем коде. Обновление до Leaflet 1.0.1 делает его более подходящим (например, LatLng(51.49868, -0.1018) против LatLng(51.4987, -0.1018)), но эти два местоположения все еще не совсем одинаковы.

Я прикрепляю L.DomEvent к правильной штуке? Должно ли это быть привязано к карте div как-то, в отличие от document?

Редактировать: Благодаря @AlexParij за предложение. Я понял, что панорамирование карты также делает клики не соответствующими, с или без div элементов над картой. Это происходит для Leaflet 1.0.1, а также для 0.7.7. Я пробовал все комбинации я могу думать, комбинируя различные места событий (event.layerX, event.pageX, event.clientX, event.offsetX, event.screenX и event.x) с проекционными методами layerPointToLatLng и unproject, но ни один из них не соответствуют карте нажмите. Теперь я действительно запутался ... Скрипт с этими различными вариантами и Листовка 1.0.1: https://jsfiddle.net/c4tkyewz/

+1

Я бы сказал, посмотрим на направление Layer Point против Container Point. http://gis.stackexchange.com/questions/69124/leaflet-container-coordinates-vs-layer-coordinates –

+0

@AlexParij Спасибо за предложение. Это заставило меня понять, что если я панорамирую карту, объекты «LatLng» даже не близки.Это справедливо без каких-либо делений над картой, а также для Листов 0.7.7 или Листов 1.0.1. Я пробовал все варианты, которые я мог бы думать о 'event.layerX',' event.pageX', 'event.clientX',' event.offsetX', 'event.screenX' и' event.x, 'в сочетании с' layerPointToLatLng', 'unproject' и' layerPointToContainerPoint', но ни один из них не соответствует. Теперь я действительно смущен ... Fiddle with Leaflet 1.0.1: https://jsfiddle.net/c4tkyewz/ – user2441511

ответ

0

TL; DR: использовать map.mouseEventToLatLng() в пользовательский обработчик.


@AlexParij был прав; Я не использовал правильное определение точек слоя и точек контейнера. Внутри обработчика event отличается от внутреннего события мыши (где местоположение доступно от e.latlng).

Я просмотрел ядро ​​Листа, чтобы найти ответ. Получение местоположения от event требует принятия события мыши -> Контейнерная точка -> Точка слоя -> latLng. К счастью, разработчики Leaflet уже запрограммировали хорошую функцию для этого: mouseEventToLatLng().

/* 
* This is a custom handler to check if someone has control clicked 
* the map and print the location of the click 
*/ 
L.CtrlClickHandler = L.Handler.extend({ 
    addHooks: function() { 
    L.DomEvent.on(document, 'click', this._captureClick, this); 
    }, 

    removeHooks: function() { 
    L.DomEvent.off(document, 'click', this._captureClick, this); 
    }, 

    _captureClick: function(event) { 
    if (event.ctrlKey) { 
     // translate mouse event to lat/lng (note: `mouseEventToLatLng()` 
     // calls Leaflet's `mouseEventToContainerPoint()` followed by 
     // `containerPointToLayerPoint()` and finally `layerPointToLatLng()`) 
     var latlng = map.mouseEventToLatLng(event); 
     console.log('Handler detected CTRL + click at ' + latlng); 
    } 
    } 
}); 

// add this to all maps 
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler); 

Живой пример с листовкой 1.0.1: https://jsfiddle.net/c4tkyewz/1/

Также протестирован с листовкой 0.7.7.


В качестве бонуса, чтобы получить доступ к ключу CTRL непосредственно из собственной обработки Лифлета события click map.on('click', function(e) {});, используйте e.originalEvent.ctrlKey.

Смежные вопросы