<style>
/* Скрываем системный курсор */
* {
cursor: none !important;
}
/* --- Стили кастомного курсора --- */
.custom-cursor {
position: fixed; /* фиксируем курсор относительно окна */
top: 0;
left: 0;
width: 16px; /* размер шарика */
height: 16px;
background-color: #2fc118; /* зеленый цвет по умолчанию для светлой темы */
border-radius: 50%; /* делаем круг */
pointer-events: none; /* чтобы не мешал кликам */
z-index: 99999999; /* поверх всех элементов */
transform: translate(-50%, -50%); /* смещаем центр шарика к курсору */
box-shadow:
0 0 5px #2fc118,
0 0 15px #2fc118,
0 0 30px #2fc118,
0 0 40px #2fc118; /* неоновое свечение */
transition: background-color 0.3s ease, box-shadow 0.3s ease; /* плавное изменение цвета */
}
/* --- Стили искр — маленьких светящихся точек вокруг курсора --- */
.spark {
position: fixed;
width: 8px;
height: 8px;
background-color: #2fc118; /* зеленый, как и курсор */
border-radius: 50%;
pointer-events: none; /* не мешаем кликам */
z-index: 99999998; /* чуть ниже курсора */
opacity: 0.8; /* немного прозрачные */
mix-blend-mode: screen; /* эффект свечения на фоне */
box-shadow:
0 0 6px #2fc118,
0 0 12px #2fc118,
0 0 20px #2fc118; /* сияние искр */
animation: spark-fade 0.5s ease-out forwards; /* анимация исчезновения и разбегания */
}
/* --- Анимация искр --- */
@keyframes spark-fade {
0% {
transform: translate(0, 0) scale(1); /* в начале в точке клика, полная прозрачность */
opacity: 1;
}
100% {
transform: translate(var(--dx), var(--dy)) scale(0.2); /* движемся в случайном направлении и уменьшаемся */
opacity: 0; /* исчезаем */
}
}
/* --- Стили для темной темы, меняем цвета на более тёмные и мягкие --- */
@media (prefers-color-scheme: dark) {
.custom-cursor {
background-color: #1d850e; /* темно-зеленый */
box-shadow:
0 0 5px #1d850e,
0 0 15px #1d850e,
0 0 30px #1d850e,
0 0 40px #1d850e;
}
.spark {
background-color: #1d850e;
box-shadow:
0 0 6px #1d850e,
0 0 12px #1d850e,
0 0 20px #1d850e;
}
}
/* --- Скрываем кастомный курсор и искры на мобильных устройствах (ширина ≤ 768px) --- */
@media (max-width: 768px) {
.custom-cursor,
.spark {
display: none !important;
}
}
</style>
<script>
document.addEventListener("DOMContentLoaded", () => {
// Создаем элемент кастомного курсора
const cursor = document.createElement("div");
cursor.classList.add("custom-cursor");
document.body.appendChild(cursor);
// Изначальное положение курсора — центр экрана
let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;
// Массив для хранения активных искр и ограничение их количества
const sparks = [];
const maxSparks = 20;
// Функция обновления позиции кастомного курсора
function updateCursorPosition() {
// Смещаем элемент в позицию мыши с учетом трансформации (центрирование)
cursor.style.transform = `translate(${mouseX}px, ${mouseY}px) translate(-50%, -50%)`;
}
// Функция создания искры при движении курсора
function createSpark(x, y) {
const spark = document.createElement("div");
spark.classList.add("spark");
// Генерируем случайное направление и расстояние для искры
const angle = Math.random() * 2 * Math.PI; // угол в радианах
const radius = Math.random() * 20 + 10; // расстояние от центра курсора (10–30px)
const dx = Math.cos(angle) * radius + "px"; // смещение по X
const dy = Math.sin(angle) * radius + "px"; // смещение по Y
// Устанавливаем позицию искры на текущую позицию курсора
spark.style.left = `${x}px`;
spark.style.top = `${y}px`;
// Передаем смещения для анимации в CSS-переменные
spark.style.setProperty('--dx', dx);
spark.style.setProperty('--dy', dy);
// Добавляем искру в DOM и массив
document.body.appendChild(spark);
sparks.push(spark);
// Если искр слишком много, удаляем самую старую
if (sparks.length > maxSparks) {
const oldSpark = sparks.shift();
oldSpark.remove();
}
// Автоматически удаляем искру из DOM после окончания анимации (0.5s)
setTimeout(() => spark.remove(), 500);
}
// Событие движения мыши — обновляем позицию и создаём искру
document.addEventListener("mousemove", e => {
mouseX = e.clientX;
mouseY = e.clientY;
updateCursorPosition();
createSpark(mouseX, mouseY);
});
// Начальное обновление позиции курсора при загрузке страницы
updateCursorPosition();
});
</script>