Обновление стилей и функционала модальных окон, добавление новых услуг и их описаний

This commit is contained in:
adlevin
2025-08-05 16:57:41 +03:00
parent 1811c43e7a
commit 70bac69e0d
5 changed files with 406 additions and 275 deletions

View File

@@ -16,7 +16,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Navbar scroll effect
initNavbarScroll();
// Animation on scroll
// Animation on scroll - плавные анимации появления
initScrollAnimations();
// Service modal functionality
@@ -218,26 +218,6 @@ function initNavbarScroll() {
});
}
// Scroll Animations
function initScrollAnimations() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('fade-in-up');
}
});
}, observerOptions);
// Observe elements that should animate on scroll
const animateElements = document.querySelectorAll('.service-card, .feature, .contact-item, .section-header');
animateElements.forEach(el => observer.observe(el));
}
// Initialize Yandex Map
function initMap() {
// Check if Yandex Maps API is loaded
@@ -458,6 +438,8 @@ function initServiceModal() {
const modalDescription = modal.querySelector('.modal-description');
const modalProcedures = document.getElementById('modal-procedures');
let scrollPosition = 0;
// Открытие модального окна
serviceCards.forEach(card => {
card.addEventListener('click', function() {
@@ -465,6 +447,9 @@ function initServiceModal() {
const serviceData = servicesData[serviceKey];
if (serviceData) {
// Сохраняем текущую позицию скролла
scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
// Заполняем данные модального окна
modalIcon.className = serviceData.icon;
modalTitle.textContent = serviceData.title;
@@ -478,17 +463,38 @@ function initServiceModal() {
modalProcedures.appendChild(li);
});
// Блокируем скролл страницы
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollPosition}px`;
document.body.style.width = '100%';
// Показываем модальное окно
modal.classList.add('active');
document.body.style.overflow = 'hidden';
}
});
});
// Закрытие модального окна
function closeModal() {
// Сначала плавно скрываем модальное окно
modal.classList.remove('active');
document.body.style.overflow = '';
// Через короткую задержку восстанавливаем скролл без эффектов
setTimeout(() => {
const currentScrollPosition = scrollPosition;
document.body.style.position = '';
document.body.style.top = '';
document.body.style.width = '';
// Отключаем smooth scroll временно
document.documentElement.style.scrollBehavior = 'auto';
window.scrollTo(0, currentScrollPosition);
// Возвращаем smooth scroll обратно
setTimeout(() => {
document.documentElement.style.scrollBehavior = 'smooth';
}, 50);
}, 100);
}
modalClose.addEventListener('click', closeModal);
@@ -500,4 +506,43 @@ function initServiceModal() {
closeModal();
}
});
// Предотвращение скролла при касании модального окна на мобильных
modal.addEventListener('touchmove', function(e) {
if (e.target === modal || e.target === modalOverlay) {
e.preventDefault();
}
}, { passive: false });
}
// Плавные scroll animations
function initScrollAnimations() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -20px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting && !entry.target.classList.contains('fade-in-up')) {
// Добавляем небольшую задержку для эффекта "волны"
setTimeout(() => {
entry.target.classList.add('fade-in-up');
}, index * 50);
// Отключаем наблюдение после анимации
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Наблюдаем за всеми элементами, которые должны анимироваться
const animateElements = document.querySelectorAll('.service-card, .feature, .contact-item, .section-header, .about-text, .stats-item');
// Изначально скрываем элементы для плавного появления
animateElements.forEach((el, index) => {
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
observer.observe(el);
});
}