iOS специфика

В отличие от настольных браузеров, iOS использует события касаний (touch events) вместо стандартных событий мыши (mousedown, mousemove, mouseup). Библиотека Shopify Draggable абстрагирует взаимодействие с различными устройствами, но для корректной работы на iOS важно понимать несколько специфических моментов:

  1. touch-action и предотвращение скролла По умолчанию iOS обрабатывает свайпы и скроллинг на элементах, что может конфликтовать с перетаскиванием. Для элементов-контейнеров Draggable необходимо установить CSS:

    .draggable-container {
        touch-action: none;
    }

    Это полностью отключает стандартное поведение жестов и позволяет Draggable корректно отслеживать движения пальца.

  2. Обработка passive событий iOS по умолчанию добавляет опцию passive: true к touchstart и touchmove, что препятствует вызову event.preventDefault(). Draggable внутри себя корректно обрабатывает этот момент, но при кастомных обработчиках важно явно указывать:

    element.addEventListener('touchmove', function(e) {
        e.preventDefault(); // необходимо для предотвращения скролла
    }, { passive: false });

Инициализация Draggable для сенсорных устройств

Draggable автоматически детектирует сенсорные устройства и использует TouchSensor вместо MouseSensor. Пример базовой инициализации:

import { Draggable } from '@shopify/draggable';

const draggable = new Draggable(document.querySelectorAll('.draggable-container'), {
    draggable: '.draggable-item',
    delay: 0,  // Задержка для сенсорных устройств
    mirror: {
        constrainDimensions: true
    }
});

draggable.on('drag:start', (event) => {
    console.log('Начало перетаскивания', event.source);
});

Особенности для iOS:

  • delay иногда требуется увеличивать на iOS, чтобы избежать конфликтов с долгими нажатиями.
  • Для плавного перетаскивания рекомендуется использовать mirror: { constrainDimensions: true }, так как на iOS transform и position: fixed могут работать иначе.

Поддержка жестов и свайпов

iOS использует touchmove с высокой чувствительностью. Для предотвращения ложных срабатываний:

  1. Минимальное смещение перед активацией drag Draggable позволяет задать delay и distance:

    const draggable = new Draggable(document.querySelectorAll('.draggable-container'), {
        draggable: '.draggable-item',
        delay: 100,   // миллисекунды
        distance: 5   // пиксели
    });

    Значение distance особенно важно на iOS, чтобы избежать активации drag при мелких случайных касаниях.

  2. Синхронизация с системным скроллом Если контейнер вертикально скроллится, нужно следить за предотвращением конфликта:

    draggable.on('drag:move', (event) => {
        event.originalEvent.preventDefault(); 
    });

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

На iOS при появлении клавиатуры изменяется viewport и поведение touch-событий. Важно учитывать:

  • Перетаскивание элементов на форме может работать некорректно из-за смещения координат.
  • Рекомендуется обновлять размеры контейнера динамически:
window.addEventListener('resize', () => {
    draggable.updateDraggables(); // пересчитывает позиции элементов
});

Ограничения CSS и производительности

  1. Transform вместо absolute На iOS для плавной анимации Draggable использует transform: translate3d(). Прямое изменение top/left может вызывать рывки и подтормаживания.

  2. Сглаживание движения Использование will-change: transform на draggable-элементах улучшает отклик на сенсорных устройствах:

    .draggable-item {
        will-change: transform;
    }
  3. Аппаратное ускорение Для тяжелых списков и сеток рекомендуется использовать requestAnimationFrame внутри кастомных событий Draggable, хотя библиотека сама обрабатывает большинство оптимизаций.


Работа с nested контейнерами

iOS чувствительна к вложенным draggable-контейнерам. Важно:

  • Явно указывать containers в настройках Draggable.
  • Использовать ignoreInputTextSelection для текстовых полей, чтобы избежать блокировки ввода:
const draggable = new Draggable(containers, {
    draggable: '.draggable-item',
    ignoreInputTextSelection: true
});

Советы по тестированию на iOS

  • Проверять на реальных устройствах: Safari, Chrome (iOS использует движок WebKit).
  • Использовать console.log(event) для отслеживания координат touch.
  • Проверять задержку между touchstart и drag:start, особенно на старых устройствах.

iOS требует внимательного подхода к обработке touch-событий, предотвращению скролла и оптимизации CSS-анимаций, чтобы Draggable работал плавно и без багов. Правильная комбинация touch-action, delay, distance и mirror.constrainDimensions обеспечивает стабильную работу на сенсорных экранах.