Реалізація 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 додатка — одна з перших фіч, яку реалізуємо після базової синхронізації документа.