ano-mr-site/front/page/main-page.js

344 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @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<string, string>} 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});
}
)()
}