Files
map_yandex/map_template.html
2025-09-23 20:13:51 +05:00

323 lines
12 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Карта образовательных учреждений Челябинска</title>
<script src="https://api-maps.yandex.ru/2.1/?apikey=YOUR_API_KEY&lang=ru_RU" type="text/javascript"></script>
<style>
body {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f5f5;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
text-align: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.header h1 {
margin: 0;
font-size: 2.2em;
font-weight: 300;
}
.header p {
margin: 10px 0 0 0;
opacity: 0.9;
font-size: 1.1em;
}
.controls {
background: white;
padding: 15px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
align-items: center;
}
.filter-btn {
padding: 8px 16px;
border: 2px solid #667eea;
background: white;
color: #667eea;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
font-weight: 500;
}
.filter-btn:hover {
background: #667eea;
color: white;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(102, 126, 234, 0.3);
}
.filter-btn.active {
background: #667eea;
color: white;
}
.stats {
text-align: center;
color: #666;
font-size: 14px;
margin-left: 20px;
}
#map {
width: 100%;
height: calc(100vh - 180px);
}
.balloon-content {
max-width: 300px;
}
.balloon-title {
font-weight: bold;
color: #333;
margin-bottom: 8px;
font-size: 16px;
}
.balloon-address {
color: #666;
margin-bottom: 8px;
font-size: 14px;
}
.balloon-specialties {
margin-bottom: 8px;
}
.specialty-tag {
display: inline-block;
background: #e8f2ff;
color: #0066cc;
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
margin: 2px;
border: 1px solid #cce7ff;
}
.balloon-contacts {
margin-top: 10px;
font-size: 13px;
}
.balloon-contacts a {
color: #667eea;
text-decoration: none;
}
.balloon-contacts a:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.header h1 {
font-size: 1.8em;
}
.controls {
padding: 10px;
}
.filter-btn {
font-size: 12px;
padding: 6px 12px;
}
.stats {
margin-left: 0;
margin-top: 10px;
width: 100%;
}
}
</style>
</head>
<body>
<div class="header">
<h1>🎓 Карта образовательных учреждений Челябинска</h1>
<p>Интерактивная карта: университеты, институты, колледжи, техникумы, лицеи и училища</p>
</div>
<div class="controls">
<button class="filter-btn active" onclick="filterBySpecialty('all')">🏛️ Все</button>
<button class="filter-btn" onclick="filterBySpecialty('Техника и технологии')">⚙️ Техника</button>
<button class="filter-btn" onclick="filterBySpecialty('Экономика и управление')">💼 Экономика</button>
<button class="filter-btn" onclick="filterBySpecialty('Медицина и здравоохранение')">🏥 Медицина</button>
<button class="filter-btn" onclick="filterBySpecialty('Педагогика и образование')">👨<EFBFBD> Педагогика</button>
<button class="filter-btn" onclick="filterBySpecialty('Строительство и архитектура')">🏗️ Строительство</button>
<button class="filter-btn" onclick="filterBySpecialty('Искусство и культура')"><EFBFBD> Искусство</button>
<button class="filter-btn" onclick="filterBySpecialty('Транспорт и логистика')"><EFBFBD> Транспорт</button>
<button class="filter-btn" onclick="filterBySpecialty('Информационные технологии')">💻 IT</button>
<button class="filter-btn" onclick="filterBySpecialty('Право и юриспруденция')">⚖️ Право</button>
<button class="filter-btn" onclick="filterBySpecialty('Пищевая промышленность')">🍳 Питание</button>
<button class="filter-btn" onclick="filterBySpecialty('Энергетика')">🏭 Энергетика</button>
<div class="stats">
<span id="showing-count">{{ colleges|length }}</span> из {{ colleges|length }} учреждений
</div>
</div>
<div id="map"></div>
<script>
let myMap;
let placemarks = [];
let colleges = {{ colleges_json|safe }};
ymaps.ready(init);
function init() {
myMap = new ymaps.Map("map", {
center: [55.1644, 61.4291], // Центр Челябинска
zoom: 11,
controls: ['zoomControl', 'searchControl', 'trafficControl', 'fullscreenControl']
});
// Добавляем метки для всех колледжей
colleges.forEach(function(college, index) {
addPlacemark(college, index);
});
// Подгоняем границы карты под все метки
if (placemarks.length > 0) {
myMap.setBounds(myMap.geoObjects.getBounds(), {
checkZoomRange: true,
zoomMargin: 50
});
}
}
function addPlacemark(college, index) {
let placemark = new ymaps.Placemark(
[college.lat, college.lon],
{
balloonContentHeader: '<div class="balloon-title">' + college.name + '</div>',
balloonContentBody: createBalloonContent(college),
balloonContentFooter: '',
hintContent: college.name,
clusterCaption: college.name
},
{
preset: 'islands#redEducationIcon',
hideIconOnBalloonOpen: false,
balloonOffset: [0, -40]
}
);
// Сохраняем данные колледжа в метке для фильтрации
placemark.college = college;
placemark.collegeIndex = index;
myMap.geoObjects.add(placemark);
placemarks.push(placemark);
}
function createBalloonContent(college) {
let content = '<div class="balloon-content">';
if (college.address) {
content += '<div class="balloon-address">📍 ' + college.address + '</div>';
}
if (college.specialties && college.specialties.length > 0) {
content += '<div class="balloon-specialties">';
content += '<strong>🎓 Специальности:</strong><br>';
college.specialties.slice(0, 5).forEach(function(specialty) {
content += '<span class="specialty-tag">' + specialty + '</span>';
});
if (college.specialties.length > 5) {
content += '<span class="specialty-tag">+' + (college.specialties.length - 5) + ' еще</span>';
}
content += '</div>';
}
if (college.description) {
content += '<div style="margin-top: 10px; font-size: 13px; color: #666;">' + college.description + '</div>';
}
let contacts = [];
if (college.phone) {
contacts.push('📞 <a href="tel:' + college.phone + '">' + college.phone + '</a>');
}
if (college.website) {
contacts.push('🌐 <a href="' + college.website + '" target="_blank">Сайт</a>');
}
if (contacts.length > 0) {
content += '<div class="balloon-contacts">' + contacts.join('<br>') + '</div>';
}
content += '</div>';
return content;
}
function filterBySpecialty(specialty) {
// Обновляем активную кнопку
document.querySelectorAll('.filter-btn').forEach(btn => btn.classList.remove('active'));
event.target.classList.add('active');
let visibleCount = 0;
placemarks.forEach(function(placemark) {
let college = placemark.college;
let shouldShow = false;
if (specialty === 'all') {
shouldShow = true;
} else {
// Проверяем специальности и название колледжа
let searchText = (college.name + ' ' + college.specialties.join(' ')).toLowerCase();
shouldShow = searchText.includes(specialty.toLowerCase());
}
if (shouldShow) {
placemark.options.set('visible', true);
visibleCount++;
} else {
placemark.options.set('visible', false);
}
});
// Обновляем счетчик
document.getElementById('showing-count').textContent = visibleCount;
// Подгоняем карту под видимые метки
if (visibleCount > 0) {
let visiblePlacemarks = placemarks.filter(p => p.options.get('visible'));
if (visiblePlacemarks.length > 0) {
let bounds = [];
visiblePlacemarks.forEach(p => {
bounds.push(p.geometry.getCoordinates());
});
myMap.setBounds(ymaps.util.bounds.fromPoints(bounds), {
checkZoomRange: true,
zoomMargin: 50
});
}
}
}
// Добавляем обработчик изменения размера окна
window.addEventListener('resize', function() {
if (myMap) {
myMap.container.fitToViewport();
}
});
</script>
</body>
</html>