xaxaxax
This commit is contained in:
323
map_template.html
Normal file
323
map_template.html
Normal file
@@ -0,0 +1,323 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user