344 lines
12 KiB
JavaScript
344 lines
12 KiB
JavaScript
/**
|
||
* @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});
|
||
}
|
||
)()
|
||
} |