Реализация Live Cursors (курсоры других пользователей) в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1735 услуг
Реализация Live Cursors (курсоры других пользователей) в мобильном приложении
Сложный
~2-3 дня
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    495

Реализация Live Cursors (курсоры других пользователей) в мобильном приложении

Live cursors — один из тех элементов UX, которые выглядят просто, а реализация требует баланса между плавностью анимации, реальным трафиком и корректным масштабированием при десятках одновременных пользователей.

На вебе это решается через CSS-анимацию и transform: translate(). На мобиле — нативные Animated API или react-native-reanimated, UIView animation или Flutter AnimatedWidget. Сетевой уровень — Y.js Awareness или кастомный WebSocket-протокол.

Протокол: Awareness vs кастомный канал

Y.js Awareness Protocol — правильный выбор, если в приложении уже есть Y.js для синхронизации контента. Awareness хранит ephemeral-состояния: они не персистируются, не входят в историю изменений, автоматически удаляются при отключении пользователя.

// Обновляем позицию своего курсора
provider.awareness.setLocalStateField('cursor', {
  x: normalizedX,  // в координатах документа, не экрана
  y: normalizedY,
  timestamp: Date.now()
});

// Подписываемся на изменения чужих курсоров
provider.awareness.on('change', ({ updated }) => {
  updated.forEach(clientId => {
    if (clientId === provider.awareness.clientID) return;
    const state = provider.awareness.getStates().get(clientId);
    if (state?.cursor) {
      updateRemoteCursor(clientId, state.cursor);
    }
  });
});

Если Y.js не используется — кастомный WebSocket-канал с throttle 30ms (≈33fps) достаточен для плавного ощущения. Более частые обновления не дают заметного улучшения UX, но увеличивают трафик.

Нормализация координат

Критический момент: координаты курсора нужно передавать в системе координат документа, не экрана. У разных пользователей разные zoom-уровни, размеры экрана, положение scroll. Если передавать screen coordinates — курсоры будут прыгать по экрану вместо плавного следования за реальной позицией.

Для scrollable документа: cursorX = (screenX + scrollX) / scale, cursorY = (screenY + scrollY) / scale. При получении обратно: displayX = documentX * scale - scrollX. При смене zoom у получателя — позиция курсора автоматически пересчитывается.

Интерполяция: плавное движение с задержкой сети

Raw-позиции от сервера — ступенчатые, особенно при задержке 100–200ms. Нужна интерполяция.

В React Native с react-native-reanimated:

const remoteCursorX = useSharedValue(0);
const remoteCursorY = useSharedValue(0);

// При получении новой позиции от сервера
const updateCursor = (x, y) => {
  remoteCursorX.value = withSpring(x, { damping: 20, stiffness: 300 });
  remoteCursorY.value = withSpring(y, { damping: 20, stiffness: 300 });
};

const animStyle = useAnimatedStyle(() => ({
  transform: [
    { translateX: remoteCursorX.value },
    { translateY: remoteCursorY.value },
  ]
}));

withSpring добавляет пружинную интерполяцию — курсор «догоняет» реальную позицию плавно. Альтернатива: withTiming с duration: 80 — проще, менее «живой».

На Flutter: AnimationController + Tween<Offset> с CurvedAnimation(curve: Curves.easeOut).

На нативном iOS: UIViewPropertyAnimator с .interruptible option — позволяет прерывать и перезапускать анимацию при новых позициях без артефактов.

Масштабирование: 50+ пользователей

При большом количестве пользователей несколько проблем:

Трафик. N пользователей × 33fps × ~50 байт = при 50 пользователях ~82 KB/s только на cursor updates. Решение: server-side throttling (сервер не пересылает updates чаще чем раз в 50ms на клиента) + отключение курсоров для пользователей за пределами viewport.

Рендеринг. 50 анимированных вьюшек одновременно на мобиле — нагрузка. Используем Canvas-based рендеринг вместо отдельных View для каждого курсора. Рисуем все курсоры в одном CustomPainter / SKCanvas / Canvas за один проход.

Идентификация. При 50 пользователях имя под курсором нечитаемо. Показываем имя только при hover/tap на курсор, остальное время — только цветовая точка с аватаром.

Отображение имени и аватара

Имя пользователя рядом с курсором — классический UX. Реализация: floating label, которая следует за курсором с небольшим offset. Проблема: при движении к краю экрана label выходит за bounds. Нужен clamp — если курсор ближе чем X px к правому краю, label отображается слева от курсора.

Аватар вместо стандартного указателя — часто лучше, чем цветная стрелка. Круглое изображение 24px диаметром, кэшированное в памяти.

Сроки

Live cursors как отдельный компонент (без полной collaborative системы) — 1–2 недели на платформу. В контексте полноценного collaborative приложения — одна из первых фич, которую реализуем после базовой синхронизации документа.