116 lines
No EOL
4 KiB
JavaScript
116 lines
No EOL
4 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function() {
|
|
// Проверяем поддержку backdrop-filter
|
|
const hasBackdropFilter = 'backdropFilter' in document.body.style ||
|
|
'webkitBackdropFilter' in document.body.style;
|
|
|
|
if (window.innerWidth <= 768) {
|
|
console.log('Мобильное устройство - кастомный курсор отключен');
|
|
return;
|
|
}
|
|
|
|
console.log('Инициализация курсора. Поддержка backdrop-filter:', hasBackdropFilter);
|
|
|
|
// Создаем элементы
|
|
const cursorOuter = document.createElement('div');
|
|
const cursorInner = document.createElement('div');
|
|
|
|
cursorOuter.className = 'cursor-outer';
|
|
cursorInner.className = 'cursor-inner';
|
|
|
|
// Если нет поддержки backdrop-filter, используем fallback
|
|
if (!hasBackdropFilter) {
|
|
cursorOuter.style.mixBlendMode = 'difference';
|
|
cursorOuter.style.backgroundColor = 'rgba(255, 255, 255, 0.2)';
|
|
cursorInner.style.mixBlendMode = 'difference';
|
|
}
|
|
|
|
document.body.appendChild(cursorOuter);
|
|
document.body.appendChild(cursorInner);
|
|
|
|
// Скрываем стандартный курсор
|
|
document.body.style.cursor = 'none';
|
|
|
|
// Переменные для анимации
|
|
let mouseX = window.innerWidth / 2;
|
|
let mouseY = window.innerHeight / 2;
|
|
let cursorX = mouseX;
|
|
let cursorY = mouseY;
|
|
let innerX = mouseX;
|
|
let innerY = mouseY;
|
|
let isVisible = false;
|
|
|
|
// Скорость следования
|
|
const outerSpeed = 0.25;
|
|
const innerSpeed = 0.15;
|
|
|
|
// Анимация
|
|
function animate() {
|
|
// Плавное движение
|
|
cursorX += (mouseX - cursorX) * outerSpeed;
|
|
cursorY += (mouseY - cursorY) * outerSpeed;
|
|
innerX += (mouseX - innerX) * innerSpeed;
|
|
innerY += (mouseY - innerY) * innerSpeed;
|
|
|
|
// Применяем позиции
|
|
cursorOuter.style.transform = `translate(${cursorX}px, ${cursorY}px)`;
|
|
cursorInner.style.transform = `translate(${innerX}px, ${innerY}px)`;
|
|
|
|
requestAnimationFrame(animate);
|
|
}
|
|
|
|
// Отслеживание мыши
|
|
document.addEventListener('mousemove', (e) => {
|
|
mouseX = e.clientX;
|
|
mouseY = e.clientY;
|
|
|
|
if (!isVisible) {
|
|
cursorOuter.style.opacity = '1';
|
|
cursorInner.style.opacity = '1';
|
|
isVisible = true;
|
|
}
|
|
});
|
|
|
|
// Ховер-эффекты
|
|
const interactive = document.querySelectorAll(
|
|
'a, button, .photo-card, .number, .photo-container, img, .navigation a'
|
|
);
|
|
|
|
interactive.forEach(el => {
|
|
el.addEventListener('mouseenter', () => {
|
|
cursorOuter.style.width = '90px';
|
|
cursorOuter.style.height = '90px';
|
|
cursorOuter.style.borderWidth = '3px';
|
|
});
|
|
|
|
el.addEventListener('mouseleave', () => {
|
|
cursorOuter.style.width = '70px';
|
|
cursorOuter.style.height = '70px';
|
|
cursorOuter.style.borderWidth = '2px';
|
|
});
|
|
});
|
|
|
|
// Скрываем при выходе из окна
|
|
document.addEventListener('mouseleave', () => {
|
|
cursorOuter.style.opacity = '0';
|
|
cursorInner.style.opacity = '0';
|
|
isVisible = false;
|
|
});
|
|
|
|
// Показываем при входе в окно
|
|
document.addEventListener('mouseenter', () => {
|
|
if (document.body.style.cursor === 'none') {
|
|
cursorOuter.style.opacity = '1';
|
|
cursorInner.style.opacity = '1';
|
|
isVisible = true;
|
|
}
|
|
});
|
|
|
|
// Запускаем анимацию
|
|
animate();
|
|
|
|
// Обновляем при ресайзе
|
|
window.addEventListener('resize', () => {
|
|
mouseX = Math.min(mouseX, window.innerWidth);
|
|
mouseY = Math.min(mouseY, window.innerHeight);
|
|
});
|
|
}); |