class MapApp {
constructor() {
this.map = null;
this.layerManager = new LayerManager();
this.sidebarManager = null;
this.coordinatesBalloon = null;
this.rasterLayer = null;
}
init() {
ymaps.ready(() => {
this.createMap();
this.sidebarManager = new SidebarManager(this);
this.loadCollectionInfo();
this.loadAllObjects();
this.initCoordinatesTool();
this.initMapClickHandler();
});
}
createMap() {
this.map = new ymaps.Map("map", {
center: [55.89724, 37.81824],
zoom: 15,
type: 'yandex#satellite'
});
}
// Инициализация инструмента координат
initCoordinatesTool() {
this.map.events.add('click', (e) => {
const coords = e.get('coords');
const lat = coords[0].toFixed(5);
const lon = coords[1].toFixed(5);
this.showCoordinatesBalloon(coords, `${lat}, ${lon}`);
});
}
// Обработчик кликов по карте (не по объектам)
initMapClickHandler() {
this.map.events.add('click', (e) => {
// Если кликнули не по объекту (по карте)
if (!e.get('target').properties) {
// Закрываем балун координат
this.closeCoordinatesBalloon();
// Закрываем панель объекта
if (this.sidebarManager && this.sidebarManager.isDetailsPanelOpen()) {
this.sidebarManager.hideObjectDetails();
}
}
});
}
// Показать балун с координатами
showCoordinatesBalloon(coords, coordString) {
if (this.coordinatesBalloon) {
this.coordinatesBalloon.close();
}
this.coordinatesBalloon = new ymaps.Balloon(this.map, {
content: this.createCoordinatesContent(coordString),
layout: 'default#imageWithContent',
position: coords
});
this.coordinatesBalloon.open(coords);
}
// Создание содержимого балуна
createCoordinatesContent(coordString) {
return `
${coordString}
`;
}
// Закрытие балуна координат
closeCoordinatesBalloon() {
if (this.coordinatesBalloon) {
this.coordinatesBalloon.close();
this.coordinatesBalloon = null;
}
}
// Добавление растрового слоя
async addRasterLayer(config) {
try {
const style = this.getRasterStyle(config.layers);
const rasterLayer = new ymaps.GeoObject({
geometry: {
type: 'Rectangle',
coordinates: config.bounds
}
}, {
fillMethod: 'stretch',
fillImageHref: config.url,
fillOpacity: style.fillOpacity || config.opacity || 0.7,
stroke: false,
zIndex: style.zIndex || 100
});
if (this.sidebarManager) {
this.sidebarManager.addRasterLayer(config, rasterLayer);
}
return rasterLayer;
} catch (error) {
console.error('Ошибка загрузки растрового слоя:', config.name, error);
}
}
// Получение стилей для растровых слоев
getRasterStyle(layers) {
if (layers && layers.length > 0) {
for (let layer of layers) {
const layerKey = `layer:${layer}`;
if (StyleRules[layerKey]) {
return StyleRules[layerKey];
}
}
}
return {};
}
async loadCollectionInfo() {
try {
const response = await fetch('data/collection.json');
const collection = await response.json();
console.log('Коллекция загружена:', collection.name);
document.title = collection.name;
} catch (error) {
console.error('Ошибка загрузки коллекции:', error);
}
}
async loadRasterLayers() {
try {
const response = await fetch('data/raster-configs.json');
const config = await response.json();
console.log('Загружено растровых слоев:', config.rasters.length);
for (const rasterConfig of config.rasters) {
await this.addRasterLayer(rasterConfig);
}
} catch (error) {
console.error('Ошибка загрузки конфига растров:', error);
}
}
async loadAllObjects() {
try {
const objectsList = await this.getObjectsList();
console.log(`Найдено объектов: ${objectsList.length}`);
const loadPromises = objectsList.map(file =>
this.loadObject(`data/objects/${file}`)
);
await Promise.all(loadPromises);
console.log('Все объекты загружены и отображены');
await this.loadRasterLayers();
this.sidebarManager.applyInitialVisibility();
} catch (error) {
console.error('Ошибка загрузки объектов:', error);
}
}
async getObjectsList() {
try {
const response = await fetch('data/objects-index.json');
const index = await response.json();
console.log(`Загружен индекс: ${index.files.length} файлов`);
return index.files;
} catch (error) {
console.error('Ошибка загрузки objects-index.json:', error);
return [];
}
}
async loadObject(filePath) {
try {
const response = await fetch(filePath);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const feature = await response.json();
console.log(`Загружен: ${feature.properties.name}`);
const mapObjects = this.layerManager.addObject(feature, this.map);
const fileName = filePath.split('/').pop().replace('.json', '');
this.sidebarManager.addObject(feature, mapObjects.main, mapObjects.vertices, fileName);
} catch (error) {
console.error(`Ошибка загрузки ${filePath}:`, error);
}
}
}
// Глобальные функции для кнопок в балуне
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
console.log('Координаты скопированы: ' + text);
}).catch(err => {
console.error('Ошибка копирования: ', err);
});
}
function closeCoordinatesBalloon() {
if (window.app && window.app.closeCoordinatesBalloon) {
window.app.closeCoordinatesBalloon();
}
}
const app = new MapApp();
window.app = app;
app.init();