Кастомные курсоры и указатели

Кастомные курсоры позволяют изменить стандартный указатель мыши на любой визуальный элемент, создавая уникальный пользовательский интерфейс. В JavaScript реализация кастомного курсора строится на отслеживании событий движения мыши и динамическом позиционировании DOM-элемента.

const cursor = document.createElement('div');
cursor.classList.add('custom-cursor');
document.body.appendChild(cursor);

document.addEventListener('mousemove', (e) => {
    cursor.style.left = `${e.clientX}px`;
    cursor.style.top = `${e.clientY}px`;
});

Ключевые моменты:

  • Создание элемента: Курсор — это отдельный элемент DOM, который можно стилизовать через CSS.
  • Отслеживание движения мыши: Событие mousemove предоставляет координаты курсора.
  • Позиционирование: Для плавного движения используется CSS-свойство transform: translate(-50%, -50%), чтобы центр элемента совпадал с курсором.
.custom-cursor {
    width: 20px;
    height: 20px;
    border: 2px solid #000;
    border-radius: 50%;
    position: fixed;
    pointer-events: none;
    transform: translate(-50%, -50%);
    transition: background 0.3s, transform 0.1s;
}

Сглаженное движение курсора

Прямое присваивание координат мыши делает движение курсора резким. Для создания плавного эффекта применяются методы интерполяции, такие как линейная интерполяция (lerp):

let mouseX = 0, mouseY = 0;
let cursorX = 0, cursorY = 0;

document.addEventListener('mousemove', (e) => {
    mouseX = e.clientX;
    mouseY = e.clientY;
});

function animate() {
    cursorX += (mouseX - cursorX) * 0.1;
    cursorY += (mouseY - cursorY) * 0.1;
    cursor.style.transform = `translate(${cursorX}px, ${cursorY}px)`;
    requestAnimationFrame(animate);
}

animate();

Принцип работы:

  • mouseX и mouseY — текущие координаты мыши.
  • cursorX и cursorY — текущие координаты кастомного курсора.
  • Множитель 0.1 задает скорость следования курсора.

Такое решение делает движение курсора плавным и естественным.


Интерактивные состояния курсора

Кастомный курсор можно менять в зависимости от взаимодействия с элементами страницы:

const links = document.querySelectorAll('a');

links.forEach(link => {
    link.addEventListener('mouseenter', () => cursor.classList.add('hover'));
    link.addEventListener('mouseleave', () => cursor.classList.remove('hover'));
});

CSS для состояний:

.custom-cursor.hover {
    transform: translate(-50%, -50%) scale(2);
    background: rgba(0, 0, 0, 0.2);
}

Особенности:

  • Использование mouseenter и mouseleave позволяет динамически менять стиль курсора.
  • Свойство scale увеличивает элемент курсора при наведении на интерактивные элементы.
  • Анимация плавного увеличения достигается с помощью CSS transition.

Комбинирование кастомного курсора с Smooth Scroll

Smooth Scroll влияет на координаты элементов при прокрутке страницы. При использовании кастомного курсора необходимо учитывать смещение страницы:

let scrollY = 0;

window.addEventListener('scroll', () => {
    scrollY = window.scrollY;
});

function animateCursor() {
    cursorX += (mouseX - cursorX) * 0.1;
    cursorY += (mouseY - cursorY + scrollY) * 0.1;
    cursor.style.transform = `translate(${cursorX}px, ${cursorY}px)`;
    requestAnimationFrame(animateCursor);
}

animateCursor();

Замечания:

  • При наличии Smooth Scroll координаты мыши и курсора нужно синхронизировать с текущей прокруткой.
  • Любые эффекты с position: fixed остаются корректными, но для элементов с position: absolute требуется корректировка на смещение.

Расширенные эффекты и динамика

Для создания более выразительных кастомных курсоров применяются дополнительные техники:

  1. Трейл-эффекты — несколько элементов, которые следуют за курсором с задержкой, создавая визуальный шлейф.
  2. Реакция на скорость движения — изменение размера или цвета курсора в зависимости от скорости мыши:
let lastX = 0, lastY = 0;

function animateSpeed() {
    const dx = mouseX - lastX;
    const dy = mouseY - lastY;
    const speed = Math.sqrt(dx*dx + dy*dy);
    cursor.style.width = `${20 + speed / 5}px`;
    cursor.style.height = `${20 + speed / 5}px`;
    lastX = mouseX;
    lastY = mouseY;
    requestAnimationFrame(animateSpeed);
}

animateSpeed();
  1. Интерактивные элементы внутри курсора — можно помещать иконки или динамический текст, который меняется при наведении на разные секции.

Производительность и оптимизация

Кастомные курсоры активно используют requestAnimationFrame, что позволяет синхронизировать анимацию с перерисовкой браузера. Для высокой производительности важно:

  • Не создавать тяжелые DOM-элементы для каждого кадра.
  • Использовать CSS-перемещения через transform вместо top/left.
  • Минимизировать обработку событий внутри mousemove, оставляя только обновление целевых координат.

Поддержка мобильных устройств

На сенсорных устройствах курсор не нужен, поэтому применяются условия:

if (!('ontouchstart' in window)) {
    document.body.appendChild(cursor);
}

Это предотвращает лишние элементы и повышает производительность на планшетах и смартфонах.


Кастомные курсоры в сочетании с Smooth Scroll и динамическими эффектами позволяют создавать богатые визуальные интерфейсы, управляя вниманием пользователя и добавляя уникальность веб-странице.