127 lines
5.1 KiB
JavaScript
127 lines
5.1 KiB
JavaScript
/**
|
|
* @typedef {Object} PopupManagerArg
|
|
* @property {ol.Map} map - ol-карта
|
|
* @property {HTMLElement} popup_div - контейнер всплывающего окна
|
|
* @property {HTMLElement} [popup_close] - закрывашка
|
|
* @property {(feature: ol.Feature) => void} map_on - поведение при нажатии на map
|
|
* @property {[number, number]} offset - смещение popup
|
|
*/
|
|
|
|
/**
|
|
* Управление и создание ol-popup
|
|
*
|
|
* @class PopupManager
|
|
* @property {ol.Map} map - ol-карта
|
|
* @property {HTMLElement} popup_div - контейнер всплывающего окна
|
|
* @property {HTMLElement} [popup_close] - закрывашка
|
|
* @property {(feature: ol.Feature) => void} map_on - поведение при нажатии на map
|
|
*/
|
|
class PopupManager {
|
|
/**
|
|
* @param {PopupManagerArg} args
|
|
*/
|
|
constructor ({map, popup_div, popup_close, map_on = (feature) => {}, offset = [0, 0]}) {
|
|
/** Безопасный вызов */
|
|
recovery(
|
|
/**
|
|
* @function
|
|
* @param {PopupManager} self
|
|
*/
|
|
self => {
|
|
/** Инъекция карты */
|
|
if(map && map instanceof ol.Map) self.map = map
|
|
else throw new Error("Аргумент 'map' невалиден")
|
|
|
|
/** Инъекция поведения при нажатии на map */
|
|
this.set_map_on(map_on)
|
|
|
|
/** Инъекция popup-элемента */
|
|
if(popup_div && popup_div instanceof HTMLElement)
|
|
self.popup_div = popup_div
|
|
else throw new Error("Аргумент 'popup_div' невалиден")
|
|
|
|
/** Инициализация popup-элемента */
|
|
self.overlay = new ol.Overlay({
|
|
element: self.popup_div,
|
|
autoPan: true,
|
|
offset: offset
|
|
})
|
|
|
|
/** Регристрация overlay */
|
|
self.map.addOverlay(self.overlay)
|
|
|
|
/** Добавление поведения при нажатии на карту */
|
|
self.map.on('click', evt => {
|
|
/** Получение данных маркера */
|
|
const feature = self.map.forEachFeatureAtPixel(
|
|
evt.pixel,
|
|
(feature, _) => feature,
|
|
{ hitTolerance: 8 }
|
|
)
|
|
if(feature) {
|
|
/** Вызов переданной функции */
|
|
self.map_on(feature)
|
|
|
|
/** Прилинковка popup */
|
|
self.set_popup(feature.getGeometry().getCoordinates())
|
|
} else {
|
|
/** Олинковка popup */
|
|
self.set_popup()
|
|
}
|
|
})
|
|
|
|
/** При нажатии не на маркеры убрать popup */
|
|
document.addEventListener('click', event => {
|
|
if (!event.target.closest('.ol-viewport') && !event.target.closest('.popup')) {
|
|
self.set_popup()
|
|
}
|
|
})
|
|
|
|
/** Инъекция и инициалиазция закрывашки (если есть) */
|
|
if(popup_close) {
|
|
/** Инъекция закрывашки */
|
|
if (popup_close instanceof HTMLElement) self.popup_close = popup_close
|
|
else throw new Error("Аргумент 'popup_close' невалиден")
|
|
|
|
/** Инициаилазиця закрывашки */
|
|
self.popup_close.onclick = function () {
|
|
/** Отлинковка от координат */
|
|
self.set_popup()
|
|
/** Скрытие */
|
|
popup_close.blur()
|
|
return false
|
|
}
|
|
}
|
|
},
|
|
(...e) => {
|
|
console.log("Ошибка при инициалиазции PopupManager");
|
|
e.forEach(er => {throw er});
|
|
}
|
|
) (this)
|
|
}
|
|
|
|
/**
|
|
* @function
|
|
* @param {[number, number] | undefined} [coord] - координаты привязки
|
|
*/
|
|
set_popup = recovery(
|
|
(coord = undefined) => this.overlay.setPosition(coord),
|
|
(...e) => {
|
|
console.log("Ошибка скрытии popup (PopupManager.set_popup)");
|
|
e.forEach(er => {throw er});
|
|
}
|
|
)
|
|
|
|
/**
|
|
* Изменение поведения при нажатии на map
|
|
* @function
|
|
* @param {(feature: Object) => void} map_on - поведение при нажатии на map
|
|
*/
|
|
set_map_on = recovery(
|
|
map_on => this.map_on = map_on,
|
|
(...e) => {
|
|
console.log("Ошибка при инициалиазции PopupManager.set_map_on");
|
|
e.forEach(er => {throw er});
|
|
}
|
|
)
|
|
} |