Как реализовать подобный эффект прокрутки?

На странице имеется блок, отвечающий за сортировку изображений. При использовании мобильного устройства мы можем просто прокручивать документ, и в этом случае сортировка остается заблокированной, независимо от того, свайпнули мы по блоку или нет. Однако, как только мы удерживаем элемент блока в течение одной секунды, сортировка активируется. 

Сложность заключается в том, что свайп по блоку и прокрутка документа одновременно распознаются как событие touchmove, что затрудняет их различение. Кроме того, перетаскивание элементов также рассматривается как touchmove как для документа, так и для элемента. 

Как можно сделать так, чтобы при свайпе по блоку активация сортировки происходила, а в случае перетаскивания элементов не возникало ложного срабатывания прокрутки документа или блока?
  • 12 сентября 2024 г. 6:23
Ответы на вопрос 2
Для реализации подобного эффекта прокрутки и активации сортировки изображений, вам необходимо воспользоваться комбинацией событий `touchstart`, `touchmove` и `touchend`, а также обработать задержку в одну секунду для активации сортировки.

Ниже приведен общий алгоритм и пример кода для реализации данного функционала:

1. **Определение переменных состояния**: Вам нужно добавить переменные, чтобы отслеживать состояние свайпа, таймер и направление движения.

2. **Обработка событий касания**:
   - **touchstart**: При начале касания инициируйте таймер и запоминайте начальные координаты касания.
   - **touchmove**: При перемещении сравните текущее движение с ранее сохранёнными координатами, чтобы определить, движется ли пользователь по блоку (свайп) или пытается перетаскивать элементы.
   - **touchend**: Отмените таймер или активируйте сортировку в зависимости от того, была ли выполнена задержка.

3. **Настройка блокировки прокрутки**: Если вы определяете, что это перетаскивание, отключите дальнейшие события прокрутки для документа.

Вот пример кода на JavaScript:

```javascript
const sortBlock = document.getElementById('sortBlock');
let touchStartX = 0;
let touchStartY = 0;
let isSwiping = false;
let isSortingActive = false;
let swipeTimer;

sortBlock.addEventListener('touchstart', (e) => {
    touchStartX = e.touches[0].clientX;
    touchStartY = e.touches[0].clientY;
    isSwiping = false;

    // Start a timer for the swipe activation
    swipeTimer = setTimeout(() => {
        isSortingActive = true;
        activateSorting(); // Функция активации сортировки
    }, 1000);
});

sortBlock.addEventListener('touchmove', (e) => {
    let diffX = e.touches[0].clientX - touchStartX;
    let diffY = e.touches[0].clientY - touchStartY;

    if (!isSortingActive) {
        if (Math.abs(diffX) > Math.abs(diffY)) {
            isSwiping = true; // Определяем, что это свайп
            e.preventDefault(); // Блокируем прокрутку документа
        } else {
            isSwiping = false; // Это перетаскивание
        }
    }
});

sortBlock.addEventListener('touchend', (e) => {
    clearTimeout(swipeTimer); // Отменяем таймер

    if (isSortingActive) {
        // Если сортировка активирована, можно здесь положить код для ее деактивации при необходимости
        isSortingActive = false; // Сбросить состояние, если нужно
    }

    // Обнуляем состояния
    touchStartX = 0;
    touchStartY = 0;
    isSwiping = false;
});

function activateSorting() {
    console.log('Сортировка активирована!');
    // Здесь можно добавить код для активации сортировки изображений
}
```

### Важно:
- Обязательно добавьте проверку, чтобы избежать срабатывания активации сортировки, если это было перетаскивание.
- Если нужно, добавьте более сложные проверки на `touchmove`, чтобы отличать свайпы от перетаскиваний более точно (например, можно установить пороговые значения для `diffX` и `diffY`).
- Не забывайте тестировать функционал на разных устройствах, чтобы убедиться, что поведение соответствует ожиданиям.
<pre><code class="javascript">$( ".selector" ).sortable({
  scroll: false,
  delay: 1000
});</code></pre>
Похожие вопросы