Обработка событий касаний

React Aria предоставляет мощный набор хуков и утилит для управления пользовательскими взаимодействиями, включая обработку касаний на мобильных и сенсорных устройствах. Основной принцип заключается в абстрагировании сложностей нативных событий touchstart, touchmove, touchend и touchcancel в удобные React-хуки, которые работают согласованно на разных платформах и браузерах.


Использование usePress для касаний

Хук usePress позволяет отслеживать нажатия и касания на интерактивных элементах. Он объединяет события мыши, клавиатуры и сенсорного экрана, обеспечивая единый интерфейс.

import {usePress} from '@react-aria/interactions';
import {useRef} from 'react';

function TouchButton() {
  let ref = useRef();
  let {pressProps, isPressed} = usePress({
    onPressStart: () => console.log('Начало касания'),
    onPressEnd: () => console.log('Конец касания'),
    onPress: () => console.log('Нажатие завершено')
  });

  return (
    <button {...pressProps} ref={ref}>
      {isPressed ? 'Нажато' : 'Нажми меня'}
    </button>
  );
}

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

  • onPressStart срабатывает сразу при касании, до отпускания.
  • onPressEnd вызывается при завершении касания, даже если элемент был перемещен.
  • onPress срабатывает только если касание завершилось на том же элементе, что и начало.

Обработка свайпов и жестов с useDrag

Для сложных интерактивных элементов, таких как слайдеры или перетаскиваемые панели, React Aria предлагает useDrag. Он отслеживает движение пальца и преобразует его в данные о смещении и скорости.

import {useDrag} from '@react-aria/interactions';
import {useRef, useState} from 'react';

function DraggableBox() {
  let ref = useRef();
  let [position, setPosition] = useState({x: 0, y: 0});

  let {dragProps} = useDrag({
    onDragMove: (e) => setPosition({
      x: position.x + e.delta.x,
      y: position.y + e.delta.y
    }),
    onDragEnd: (e) => console.log('Перетаскивание завершено', e)
  });

  return (
    <div
      {...dragProps}
      ref={ref}
      style={{
        width: 100,
        height: 100,
        backgroundColor: 'salmon',
        transform: `translate(${position.x}px, ${position.y}px)`
      }}
    />
  );
}

Особенности работы:

  • onDragMove обеспечивает плавное перемещение, автоматически учитывая устройство ввода.
  • delta — смещение за текущее событие движения, полезно для плавных анимаций.
  • onDragEnd вызывается при завершении касания или отпускании мыши.

События касаний и совместимость с клавиатурой

React Aria стремится к универсальности интерфейсов, поэтому многие хуки для сенсорных событий работают и с клавиатурой. Это позволяет создавать доступные компоненты без отдельной логики для keydown или keyup.

Пример объединенного обработчика:

import {usePress} from '@react-aria/interactions';
import {useRef} from 'react';

function AccessibleCard() {
  let ref = useRef();
  let {pressProps} = usePress({
    onPress: () => alert('Элемент активирован')
  });

  return (
    <div {...pressProps} ref={ref} tabIndex={0} style={{padding: 20, border: '1px solid gray'}}>
      Нажмите или коснитесь
    </div>
  );
}
  • Элемент можно активировать как кликом мыши, так и касанием, и клавишей Enter или пробел.
  • tabIndex={0} делает компонент доступным для навигации с клавиатуры.

Управление жестами с useHover и useFocus

Для комплексных сенсорных интерфейсов важно различать простое касание и наведение или фокус:

  • useHover отслеживает наведение пальца на сенсорных экранах и мыши.
  • useFocus управляет фокусом и может использоваться для визуальных эффектов при выделении.
import {useHover} from '@react-aria/interactions';
import {useRef, useState} from 'react';

function HoverableBox() {
  let ref = useRef();
  let [hovered, setHovered] = useState(false);
  let {hoverProps} = useHover({
    onHoverStart: () => setHovered(true),
    onHoverEnd: () => setHovered(false)
  });

  return (
    <div
      {...hoverProps}
      ref={ref}
      style={{
        width: 120,
        height: 120,
        backgroundColor: hovered ? 'lightblue' : 'lightgray'
      }}
    />
  );
}
  • Реагирует на касания и движения пальца, обеспечивая визуальный отклик без сложной ручной логики.

Особенности работы на мобильных устройствах

  • React Aria автоматически предотвращает конфликт событий касания с прокруткой страницы.
  • Использование хуков usePress и useDrag минимизирует задержку между касанием и реакцией интерфейса.
  • Поддерживается множественный ввод (multi-touch), что позволяет создавать сложные жесты и анимации.

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

  • Для элементов с интенсивными событиями движения рекомендуется использовать requestAnimationFrame внутри onDragMove.
  • Избегать лишних перерендеров, используя useRef для хранения состояния позиции.
  • Комбинировать хуки с CSS-переходами для плавной анимации и меньшей нагрузки на рендеринг.

React Aria превращает обработку касаний в предсказуемый и совместимый с различными устройствами процесс, обеспечивая единый API для мыши, клавиатуры и сенсорного ввода. Правильное использование usePress, useDrag, useHover и useFocus позволяет создавать интерактивные, доступные и отзывчивые интерфейсы без сложной низкоуровневой логики.