Widget:KidsMap
Внешний вид
<button id="refreshMapBtn" style="background: #1565c0; color: white; border: none; padding: 6px 16px; border-radius: 20px; font-size: 14px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 🔄 Обновить карту </button>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<style> .emoji-marker {
background: white; border-radius: 50%; border: 2px solid #2e7d32; text-align: center; font-size: 18px; line-height: 28px; width: 28px !important; height: 28px !important; box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
- refreshStatus {
font-size: 12px; color: #888;
} </style>
<script> var map = L.map('map').setView([59.9343, 30.3351], 12); L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19, attribution: '© OpenStreetMap'
}).addTo(map);
function getIconByType(type) {
const icons = {
'Парк': '🌳', 'Памятник': '🗿', 'Музей': '🏛️', 'Церковь': '⛪',
'Школа': '🏫', 'Кафе': '☕', 'Мост': '🌉', 'Фонтан': '⛲',
'Театр': '🎭', 'Библиотека': '📚', 'Стадион': '⚽', 'Аквапарк': '💦',
'Зоопарк': '🐘', 'Кинотеатр': '🎬', 'Торговый центр': '🛍️',
'Вокзал': '🚂', 'Гостиница': '🏨', 'Ресторан': '🍽️', 'Набережная': '🌊',
'Сад': '🌿', 'Сквер': '🌳', 'Дворец': '🏰', 'Собор': '⛪',
'Часовня': '🕯️', 'Монастырь': '🏯', 'Улица': '🛤️', 'Переулок': '🏘️',
'Река': '🌊', 'Канал': '🌊', 'Остров': '🏝️', 'Метро': '🚇',
'Скульптура': '🗿', 'Галерея': '🖼️', 'Выставка': '🎨',
'Концертный зал': '🎵', 'Спорткомплекс': '🏟️', 'Клуб': '🎶',
'Рынок': '🏪', 'Аптека': '💊', 'Больница': '🏥', 'Университет': '🎓',
'Архив': '📜', 'Детский центр': '🧸', 'Парк аттракционов': '🎡',
'Океанариум': '🐠', 'Дельфинарий': '🐬', 'Планетарий': '🌌',
'Причал': '⚓', 'Смотровая площадка': '🌅', 'Арка': '🚪',
'Детская площадка': '🧒', 'Спортплощадка': '⚽', 'Беговая дорожка': '🏃',
'Велодорожка': '🚴', 'Скейт-парк': '🛹', 'Пляж': '🏖️',
'Пруд': '🦆', 'Озеро': '🏞️', 'Лес': '🌲', 'Карьер': '⛏️',
'Крепость': '🏯', 'Форт': '🛡️', 'Подземелье': '🕳️', 'Тоннель': '🚇',
'Бизнес-центр': '🏢', 'Хостел': '🏨', 'Дом': '🏠', 'Завод': '🏭',
'Фабрика': '🏭', 'Маяк': '🗼', 'Башня': '🗼', 'Стенд': '📋',
'Скамейка': '🪑', 'Другое': '📍'
};
return L.divIcon({
html: icons[type] || '📍',
iconSize: [28, 28],
className: 'emoji-marker',
popupAnchor: [0, -14]
});
}
function drawMarkers() {
document.getElementById('loading-message').style.display = 'block';
document.getElementById('refreshStatus').textContent = 'Загрузка...';
fetch('/data.php?_=' + Date.now())
.then(response => {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.json();
})
.then(data => {
console.log('Данные загружены, объектов:', data.length);
map.eachLayer(layer => {
if (layer instanceof L.Marker) map.removeLayer(layer);
});
data.forEach(obj => {
var lat = parseFloat(obj.lat);
var lon = parseFloat(obj.lon);
if (isNaN(lat) || isNaN(lon)) return;
var icon = getIconByType(obj.type);
var popupHtml = '' + obj.name + '
' +
'Тип: ' + obj.type + '
' +
obj.address + '
';
if (obj.quest) popupHtml += '🎯 Квест: ' + obj.quest + '
';
if (obj.image) popupHtml += '<img src="' + obj.image + '" style="max-width:150px; max-height:100px; margin-top:8px; border-radius:8px;">
';
if (obj.description) popupHtml += 'Описание: ' + obj.description + '
';
if (obj.page) popupHtml += '<a href="/index.php/' + encodeURIComponent(obj.page) + '" target="_blank">📖 Читать подробнее</a>';
L.marker([lat, lon], {icon: icon}).addTo(map).bindPopup(popupHtml);
});
document.getElementById('loading-message').style.display = 'none';
document.getElementById('refreshStatus').textContent = '✅ Обновлено (' + data.length + ' мест)';
if (data.length === 0) {
document.getElementById('loading-message').innerHTML = '😕 Нет мест. Добавь первое!';
document.getElementById('loading-message').style.display = 'block';
}
})
.catch(error => {
console.error('Ошибка загрузки данных:', error);
document.getElementById('loading-message').innerHTML = '⚠️ Не удалось загрузить данные. Попробуйте позже.';
document.getElementById('loading-message').style.display = 'block';
document.getElementById('refreshStatus').textContent = '❌ Ошибка';
});
}
function recreateCargoTable() {
return fetch('/index.php/Шаблон:Объект_en?action=recreatedata')
.then(response => {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.text();
})
.then(() => {
console.log('Таблица Cargo пересоздана');
// Ждём 1 секунду, чтобы Cargo успел обновиться
return new Promise(resolve => setTimeout(resolve, 1000));
});
}
function refreshMap() {
var status = document.getElementById('refreshStatus');
status.textContent = '⏳ Пересоздание таблицы...';
recreateCargoTable()
.then(() => {
status.textContent = '⏳ Загрузка данных...';
return drawMarkers();
})
.catch(error => {
console.error('Ошибка пересоздания таблицы:', error);
status.textContent = '⚠️ Ошибка, попробуйте позже';
// Даже если пересоздание не сработало, пробуем загрузить данные
drawMarkers();
});
}
// Инициализация drawMarkers();
// Обработчик кнопки document.getElementById('refreshMapBtn').addEventListener('click', function() {
refreshMap();
});
var attributionControl = map.attributionControl; if (attributionControl) {
attributionControl.setPrefix();
var style = document.createElement('style');
style.innerHTML = '.leaflet-attribution-flag { display: none !important; }';
document.head.appendChild(style);
} </script>