v-touch-pan жесты панорамирования

v-touch-pan — это директива, предоставляемая библиотекой Quasar, предназначенная для отслеживания жестов панорамирования на элементах пользовательского интерфейса. Она позволяет получать информацию о движении пальца по экрану или курсора мыши, фиксировать направления свайпов и управлять интерактивными компонентами, такими как карусели, карты или пользовательские панели.

Директива применяется к любому HTML-элементу и обеспечивает реакцию на горизонтальные и вертикальные движения, а также на диагональные векторы. Основная цель — дать возможность гибко управлять элементами интерфейса без необходимости напрямую обращаться к низкоуровневым событиям touch или pointer.

Синтаксис применения

Простейший пример использования выглядит так:

<template>
  <div v-touch-pan.prevent="onPan" class="pan-area">
    Перетаскиваемый блок
  </div>
</template>

<script>
export default {
  methods: {
    onPan(event) {
      console.log(event.direction, event.deltaX, event.deltaY);
    }
  }
}
</script>

<style>
.pan-area {
  width: 300px;
  height: 300px;
  background-color: #e0e0e0;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>

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

  • v-touch-pan.prevent — предотвращает стандартное поведение браузера, связанное с прокруткой.

  • Метод onPan получает объект события с полями:

    • direction — направление движения (left, right, up, down).
    • deltaX, deltaY — смещение по осям X и Y.
    • offsetX, offsetY — абсолютное смещение с момента начала жеста.
    • isFinal — флаг завершения жеста.

Параметры директивы

Директива поддерживает ряд параметров, которые позволяют гибко настраивать обработку панорамирования:

  • horizontal (Boolean) — обрабатывать только горизонтальные движения.
  • vertical (Boolean) — обрабатывать только вертикальные движения.
  • mouse (Boolean) — реагировать на движения мыши, а не только сенсорного экрана.
  • prevent (Boolean) — отменяет стандартное поведение браузера при панорамировании.
  • stop (Boolean) — останавливает всплытие события к родительским элементам.
  • threshold (Number) — минимальное смещение (в пикселях), которое нужно преодолеть, чтобы событие считалось панорамированием.

Пример с ограничением по горизонтали и порогом срабатывания:

<div v-touch-pan.horizontal.prevent.threshold="20" @pan="handlePan">
  Горизонтальная панель
</div>

Объект события v-touch-pan

Каждое событие передает детализированный объект, который содержит:

  • direction — направление: 'left', 'right', 'up', 'down'.
  • delta — объект { x, y }, текущее смещение от начала жеста.
  • offset — объект { x, y }, накопительное смещение.
  • isFirst — true для первого события после начала жеста.
  • isFinal — true для последнего события перед отпусканием.
  • velocity — скорость движения по осям.
  • touch — объект оригинального события TouchEvent.

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

Использование для анимации

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

<template>
  <div class="swipe-box" :style="{ transform: `translateX(${translateX}px)` }" v-touch-pan.horizontal.prevent="onPan">
    Перемещаемый блок
  </div>
</template>

<script>
export default {
  data() {
    return { translateX: 0 }
  },
  methods: {
    onPan(e) {
      this.translateX = e.offset.x;
      if (e.isFinal) {
        this.translateX = 0; // Возврат в исходное положение
      }
    }
  }
}
</script>

<style>
.swipe-box {
  width: 200px;
  height: 100px;
  background-color: #42a5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: bold;
  user-select: none;
}
</style>

Здесь offset.x позволяет элементу следовать за пальцем, создавая плавный интерактивный эффект. По завершении жеста (isFinal) элемент возвращается в исходное положение.

Комбинирование с другими событиями

v-touch-pan можно совмещать с другими жестами, например, с v-touch-swipe, чтобы различать короткие быстрые свайпы и длинные панорамирования. Также допустимо использование вместе с анимационными библиотеками (например, Velocity.js или встроенные CSS-переходы), что позволяет реализовать динамичные карусели и интерактивные панели.

Практические рекомендации

  • Для каруселей и слайдеров лучше использовать horizontal с порогом threshold, чтобы избежать ложных срабатываний при незначительных движениях.
  • Для карт и зон масштабирования лучше включать оба направления (horizontal + vertical) и учитывать velocity, чтобы реализовать инерцию движения.
  • Всегда использовать prevent при работе на мобильных устройствах, чтобы свайпы не инициировали нежелательную прокрутку страницы.
  • Проверять isFinal, если требуется выполнять действия только по завершению жеста, например, фиксацию позиции элемента или запуск анимации возврата.

Совместимость и производительность

v-touch-pan построен поверх стандартных событий Pointer и Touch, что обеспечивает высокую совместимость с современными браузерами и мобильными устройствами. Обработка панорамирования выполняется оптимизированно, с минимальными накладными расходами, благодаря чему можно использовать её даже для тяжелых анимационных элементов без заметного снижения производительности.

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