Файл server js: const express = require(‘express’);
const app = express();
const axios = require(‘axios’);
const path = require(‘path’);

const port = 3000;
const shapes = [];

app.use(express.static(path.join(__dirname, ‘public’)));
app.use(‘/leaflet’, express.static(path.join(__dirname, ‘node_modules/leaflet/dist’)));
app.use(‘/leaflet.draw’, express.static(path.join(__dirname, ‘node_modules/leaflet-draw/dist’)));

app.get(‘/’, (req, res) => {
res.sendFile(path.join(__dirname, ‘views’, ‘index.html’));
});

app.get(‘/data/:lat/:lng’, async (req, res) => {
const latitude = req.params.lat;
const longitude = req.params.lng;
try {
const response = await axios.get(https://overpass-api.de/api/interpreter?data=[out:json];node(around:100,${longitude});out;);
res.json(response.data.elements && response.data.elements[0] ? response.data.elements[0].tags : {});
} catch (error) {
console.log(error);
res.status(500).json({ error: ‘An error occurred’ });
}
});

app.get(‘/getShapes’, (req, res) => {
res.json(shapes);
});

app.get(‘/getShapesByButton/:type’, (req, res) => {
const type = req.params.type;
const filteredShapes = shapes.filter(shape => shape.options.tag === type);
res.json(filteredShapes);
});

app.listen(port, () => {
console.log(Server running on http://localhost:${port});
}); файл index html: <!DOCTYPE html>
<html lang=“en”>

<head>
<meta charset=“UTF-8”>
<meta name=“viewport” content=“width=device-width, initial-scale=1.0”>
<title>Leaflet Draw Map</title>
<link rel=“stylesheet” href=“/leaflet/leaflet.css” />
<link rel=“stylesheet” href=“/leaflet.draw/leaflet.draw.css” />
<style>
#map {
height: 400px;
}

#info {
margin-top: 10px;
}

.active {
background-color: yellow;
}

/* Скрыть атрибуцию /
.leaflet-control-attribution {
display: none;
}

/ Добавленные стили для всплывающей подсказки */
.map-tooltip {
background-color: white;
border: 1px solid #ccc;
padding: 5px;
font-size: 12px;
}
</style>
</head>

<body>
<div id=“buttons”>
<button id=“field” class=“active”>Поле</button>
<button id=“road”>Дорога</button>
<button id=“building”>Здание</button>
<button id=“forest”>Лес</button>
</div>
<div id=“map”></div>
<div id=“info”>
<h2>Object info:</h2>
</div>
<script src=“/leaflet/leaflet.js”></script>
<script src=“/leaflet.draw/leaflet.draw.js”></script>
<script>
const map = L.map(‘map’).setView([51.505, -0.09], 13);
L.tileLayer(‘https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png’).addTo(map);

const drawnItems = new L.FeatureGroup().addTo(map);
const drawControl = new L.Control.Draw({
draw: {
polyline: false,
polygon: true,
circle: false,
marker: false,
rectangle: true
},
edit: {
featureGroup: drawnItems
}
});
map.addControl(drawControl);

let shapes = [];

map.on(‘draw:created’, function (e) {
const layer = e.layer;
drawnItems.addLayer(layer);
const infoDiv = document.getElementById(‘info’);
infoDiv.innerHTML = ‘<h2>Object info:</h2>’;
const infoElement = document.createElement(‘p’);

if (layer.options.tag) {
infoElement.textContent = Tag: ${layer.options.tag}, ID: ${layer._leaflet_id};
} else {
infoElement.textContent = ID: ${layer._leaflet_id};
}

infoDiv.appendChild(infoElement);

shapes.push(layer);
updateObjectList();
});

map.on(‘draw:drawstart’, function (e) {
const layerType = e.layerType;
let tag = ‘’;
if (layerType === ‘rectangle’) {
tag = ‘field’;
} else if (layerType === ‘polygon’) {
tag = ‘road’;
}
drawControl.setDrawingOptions({
rectangle: {
tag: tag
},
polygon: {
tag: tag
}
});
});

const buttons = document.querySelectorAll(‘#buttons button’);
buttons.forEach(button => {
button.addEventListener(‘click’, () => {
buttons.forEach(btn => {
btn.classList.remove(‘active’);
});
button.classList.add(‘active’);
drawControl.setDrawingOptions({
rectangle: {
tag: button.id
},
polygon: {
tag: button.id
}
});
});
});

// Добавленный код для отображения названия тега при наведении на фигуру
map.on(‘mouseover’, function (e) {
const layer = e.layer;
const tag = layer.options.tag;
if (tag) {
const tooltip = L.tooltip({
permanent: true,
direction: ‘top’,
className: ‘map-tooltip’,
offset: [0, -10],
content: Tag: ${tag}
});
tooltip.setLatLng(e.latlng).addTo(map);
}
});

map.on(‘mouseout’, function () {
map.closePopup();
});

// Function to update the object list on the screen
function updateObjectList() {
const infoDiv = document.getElementById(‘info’);
infoDiv.innerHTML = ‘<h2>Object info:</h2>’;

shapes.forEach(shape => {
const listItem = document.createElement(‘p’);
const tag = shape.options.tag;
if (tag) {
listItem.textContent = Tag: ${tag}, ID: ${shape._leaflet_id};
} else {
listItem.textContent = ID: ${shape._leaflet_id};
}
infoDiv.appendChild(listItem);
});
}
</script>
</body>

</html> Это приложении присваивает тег каждой фигуре вместе с id в зависимости от того, какая кнопка выбрана?
Да, именно так. В приложении кнопки внизу страницы связаны с разными типами фигур на карте, такими как поле, дорога, здание и лес.

При клике на одну из кнопок, фигуры, нарисованные на карте, получают соответствующий тег (tag), который задан кнопке. Например, если выбрана кнопка “Поле”, то все нарисованные прямоугольники будут иметь тег “field”. То же самое относится и к фигурам, которые нарисованы с помощью инструмента “Полигон”.

Тег фигуры сохраняется в свойстве options.tag фигуры, и затем использовано при отображении информации о фигурах в информационном блоке и при создании всплывающей подсказки для каждой фигуры при наведении курсора мыши.

Функция updateObjectList() обновляет список фигур на экране, отображая их теги и идентификаторы.
У приложения есть проблемы: во первых почему то в строке objects отображается только id фигур, а теги не отображаются, во вторых возникает ошибка: (index):130 Uncaught TypeError: Cannot read properties of undefined (reading ‘options’)
at e.<anonymous> ((index):130:25)
at e.fire (Events.js:195:9)
at e._fireDOMEvent (Map.js:1452:15)
at e._handleDOMEvent (Map.js:1401:8)
at HTMLDivElement.o (DomEvent.js:108:13)
(index):130 Uncaught TypeError: Cannot read properties of und в третьих при наведении на фигуру ничего не происходит. Ты можешь исправить? Если да, то напиши обновленные файлы целиком без пропусков кода.