/** * @typedef {import ('/lib/js/ref-manager.js').RefManager} RefManager * @typedef {import('/lib/js/single-layer-manager.js').SingleLayerManager} SingleLayerManager * @typedef {import ('/lib/js/popup-manager.js').PopupManager} PopupManager * @typedef {import ('/lib/js/page-manager.js').PageManager} PageManager */ /** * Генерация функции для получения стилей маркера * @function * @param {Object} marker_refs - объект с ссылками * @returns {((feature) => ol.style.Style)} */ const gen_get_style = recovery( marker_refs => feature => recovery( () => { /** Проверка feature */ if (!feature || typeof feature.getProperties !== 'function') { throw new Error("Некорректный feature"); } /** Свойства feature */ const properties = feature.getProperties() /** Ссылка к иконке */ const url = marker_refs[properties.type.toLowerCase()] ?? marker_refs['археообъект'.toLowerCase()] /** Генерация стилей */ return new ol.style.Style({ image: new ol.style.Icon({ anchor: [0.5, 1], scale: 0.08, src: url }) }) }, (...e) => { console.log("Ошибка при получении стилей (gen_get_style->get_style)"); e.forEach(er => {throw er}); } )(), (...e) => { console.log("Ошибка генерации функции стилей (gen_get_style)"); e.forEach(er => {throw er}); } ) /** * Функция инициализирует карту * @function * @param {{coordinates: [number, number], target?: string}} arg * @returns {{map: ol.Map, layer: ol.layer.Vector}} */ const create_map_and_layer = ({coordinates, target = "map"}, style_f) => { /** Одиночный слой */ let layer = new ol.layer.VectorImage({ source: new ol.source.Vector({}), style: (feature) => style_f(feature) }) /** Создание карты и её привязка к dom-элементу */ const map = new ol.Map({ view: new ol.View({ center: ol.proj.fromLonLat(coordinates), zoom: 10, minZoom: 8 }), layers: [ new ol.layer.Tile({ source: new ol.source.OSM(), }), layer ], target: target }) return {map, layer} } /** * Активация стилей кнопки * @function */ const active = (btn) => btn.classList.replace('not-selected', 'selected') /** * Деактивация стилей кнопки * @function */ const deactive = (btn) => btn.classList.replace('selected', 'not-selected') /** * Функция инициализации главой страницы * @function * @param {PageManager} page_manager * @param {RefManager} [previous_refs_manager] - менеджер ссылок предыдущей страницы */ const main_page_init = async ({page_manager}) => { /** * Cоздание ссылок из загруженных фотографий * @function * @returns {RefManager} */ const icon_refs_manager_init = async () => { /** Данные (иконки) из внешнего json */ const icons_data = (await get('json', './icons/icons.json')) const now_icons_data = {...icons_data.markers, ...icons_data.others} /** Менеджер иконок, заполненный ссылками */ let icon_ref_manager = new RefManager() for (const [name, path] of Object.entries(now_icons_data)) icon_ref_manager.save({ key: name.toLowerCase(), ref: URL.createObjectURL(await get('file', path)) }) return icon_ref_manager } /** * Создание и ининциализация карты * @function * @param {RefManager} icon_ref_manager - менеджер ссылок * @returns {{map: ol.Map, layer: ol.layer.Vector}} */ const map_init = (icon_refs_manager) => create_map_and_layer( { coordinates: [70.008408, 60.001500], target: "map" }, gen_get_style(icon_refs_manager.get_all()) ) /** * Создание и заполнение элемента с кнопками периодов * @function * @param {Object} geojsons - объект, содержащий все geojson'ы */ const periods_init = (geojsons, single_layer_manager) => { /** DOM-элемент, куда кнопки периодов загружаются */ const time_select = document.getElementById('time-select') const periods = Object.keys(geojsons) .sort((a, b) => parseInt(a) - parseInt(b)) /** Массив кнопок с период-кнопками */ const buttons_periods = periods.map(period => { /** Период-кнопка */ const button = document.createElement('button') button.dataset.period = period; button.textContent = period; /** Добавление стилей: неактивная кнопка */ button.classList.add('not-selected') /** Добавление в панель */ time_select.appendChild(button) return button }) /** Добавление слушателей (Загрузка geojson + сохранение состояния) */ buttons_periods.forEach(bp => { bp.addEventListener('click', async () => { /** Изменение слоя на карте */ single_layer_manager.set(geojsons[bp.dataset.period]) /** Сохранение состояния */ localStorage.setItem('selected', bp.dataset.period); /** Выключение всех остальных кнопок */ buttons_periods.forEach(deactive) /** Включение текущей кнопки */ active(bp) }) }) /** Загрузка последнего сохраненного статуса-периода (Имитация выбора) */ const selected = localStorage.getItem('selected') const button_select = buttons_periods.find(bp => bp.dataset.period === selected); if (button_select) { button_select.click() } else buttons_periods[0].click() } /** * Создание и заполнение легенды (маркер - название) * @function * @param {RefManager} icon_refs_manager - менеджер ссылок */ const legend_init = (icon_refs_manager) => { /** DOM-элемент легенды */ const legend = document.getElementById('legend') for(const [name, ref] of Object.entries(icon_refs_manager.get_all())) { /** Row в легенде */ const div = document.createElement('div') /** Иконка - маркер */ const marker = document.createElement('img') /** Текст - название */ const p = document.createElement('p'); /** Помещение данных в row */ marker.src = ref p.innerHTML = name /** Добавление в контейенер легенды */ div.appendChild(marker) div.appendChild(p) legend.appendChild(div) } } /** * Создание логотипов с переходом на другие страницы * @function * @param {RefManager} icon_refs_manager - менеджер ссылок */ const logos_init = (icon_refs_manager) => { /** DOM-элемент для логотипов */ const logos = document.getElementById('logos') /** * Линковка ссылок на изображения и onclick'ов * @param {string} img_src * @param {(() => {})} onclick * @returns */ const logo_init = (img_src, onclick) => { /** Создание dom-элемента */ const logo = document.createElement('img') /** Инъекция аргументов */ logo.src = img_src logo.onclick = onclick return logo } /** Создание и добавление логотипов */ [ logo_init( icon_refs_manager.get('malaya_logo'), () => window.location.href = 'https://vk.com/anomalaya_rodina' ), logo_init( icon_refs_manager.get('rmc_logo'), () => window.location.href = 'https://vk.com/rcod_hmao' ) ].forEach(logo => logos.appendChild(logo)); } /** * Инициализация popup-manager * @function * @param {ol.Map} map - ol-карта * @param {PageManager} page_manager - менеджер страниц * @param {RefManager} refs_manager - менеджер ссылок * @param {string} close_icon - икнонка крестика * @returns {PopupManager} */ const popup_manager_init = (map, page_manager, refs_manager, close_icon) => { /** Смещение popup */ const offset = [0, 10] /** Контейнер popup */ const popup = document.getElementById('popup') /** Закрывашка, привязка ссылки иконки*/ const popup_close = document.getElementById('popup-close') popup_close.src = close_icon /** Заголовок всплывающего окна */ const popup_title = document.getElementById('popup-title') /** Контент всплывающего окна */ const popup_content = document.getElementById('popup-content') /** * Поведение карты при нажатии на карту * @param {ol.Feature} feature - объект маркера */ const map_on = feature => { /** Формирование контента */ popup_title.innerHTML = feature.getProperties().name popup_content.innerHTML = '' /** Формирование кнопки 'подробнее' и его привязка */ if (feature.getProperties().info_exist) { /** Создание ссылки 'подробнее' */ const content_description = document.createElement('a') content_description.innerHTML = 'подробнее' content_description.href = '#' /** Привязка */ popup_content.appendChild(content_description) /** Переход к info-page */ content_description.onclick = () => page_manager.set_page('info-page', { page_manager: page_manager, icon_refs_manager: refs_manager, properties: feature.getProperties() }) } } return new PopupManager({ map: map, popup_div: popup, popup_close: popup_close, offset: offset, map_on: map_on }) } /** Защищенный вызов */ await recovery( async () => { /** Получение всех иконок */ const icon_ref_manager = await icon_refs_manager_init() /** Инициализация */ const {map, layer} = map_init(icon_ref_manager) const single_layer_manager = new SingleLayerManager(layer) /** Получение всех geojson'ов */ const geojsons = await get_all_geojsons() periods_init(geojsons, single_layer_manager) legend_init(icon_ref_manager) logos_init(icon_ref_manager) popup_manager_init(map, page_manager, icon_ref_manager, icon_ref_manager.get('close')) }, (...e) => { console.log("Ошибка при инициалиазции main-page"); e.forEach(er => {throw er}); } )() }