Статьи

Плагин jQuery для сенсорного сканирования — часть 2 из 2

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

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

var Swiper = function (el, callbacks, options) { ... this.opts = options; this.swipeDone = false; //perform binding this.el.addEventListener('touchend', function (evt) { tis.stop(evt); }); .... }; Swiper.LEFT = - 1; Swiper.RIGHT = 1; ... $.fn.swiper = function (callbacks, options) { var opts = $.extend({}, $.fn.swiper.defaults, options); if (typeof callbacks.swiping !== 'function') { throw '"swiping" callback must be defined.'; } if (typeof callbacks.swiped !== 'function') { throw '"swiped" callback must be defined.'; } if (typeof callbacks.swipeCancel !== 'function') { throw '"swipeCancel" callback must be defined.'; } this.each(function () { ... if (!swiper) { tis.data('swiper', (swiper = new Swiper(this, callbacks, opts))); } }); }; $.fn.swiper.defaults = { tolerance: 100 }; 

В приведенном выше листинге мы видим, что конструктор класса для Swiper изменен, чтобы принимать параметры третьего параметра options которые содержат одно tolerance свойства. Параметр присваивается внутреннему свойству opts . Событие touchend на метод экземпляра stop() класса Swiper .

Кроме того, были добавлены две функции обратного вызова ( swipeCancel и swipeCancel ) для обработки смахивания. Значение по умолчанию для tolerance установлено как 100 (пикселей). Обратите внимание, что есть также два свойства класса Swiper.LEFT и Swiper.RIGHT . Они представляют собой пролистывание влево и вправо соответственно и будут использоваться в последующих списках.

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

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

С другой стороны, если палец преодолевает расстояние, которое меньше значения tolerance , движение не считается ударным, и карусель должна вернуться в исходное положение.

Помните, что плагин перемещает карусель, чтобы отразить движение пальца на время контакта с экраном. Решение о том, touchend положение карусели, принимается, когда палец touchend от экрана (привязка для события touchend ).

 Swiper.prototype.stop = function (evt) { if (!this.swipeDone) { this.cbs.swipeCancel(); } else { this.cbs.swiped(this.getDirection()); } }; 

Если обнаружен удар, вызовите обратный вызов для продвижения карусели ( swiped() ), в противном случае swipeCancel() карусель ( swipeCancel() ).

Стоит отметить, что мы возвращаем направление движения « getDirection вызову, как определено методом getDirection . Это необходимо, так как обратный вызов должен знать, в каком направлении двигаться вперед.

 Swiper.prototype.getDirection = function () { var direction = this.diff(); if (direction < 0) { return Swiper.LEFT; } if (direction > 0) { return Swiper.RIGHT; } }; 

Этот метод использует метод diff() определенный в части 1 этой серии, чтобы получить смещение пальца. Если разница отрицательна, это пролистывание влево, в противном случае это пролистывание вправо.

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

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

Аналогично, если пользователь возвращает палец за пределы допустимого значения, прежде чем убрать палец, его / ее намерение состоит в том, чтобы продвинуть карусель.

Как вы можете себе представить, определение того, когда жест обнаружен, выполняется во время перетаскивания пальца по экрану, а не когда палец поднят. Поэтому мы должны внести некоторые изменения в метод экземпляра move() класса Swiper .

 Swiper.prototype.move = function (evt) { if (Math.abs(this.diff()) >= this.opts.tolerance) { this.swipeDone = true; } else { this.swipeDone = false; } if (evt.targetTouches && evt.targetTouches.length === 1) { if (evt.targetTouches[0].offsetX) { this.points[1] = evt.targetTouches[0].offsetX; } else if (evt.targetTouches[0].layerX) { this.points[1] = evt.targetTouches[0].layerX; } else { this.points[1] = evt.targetTouches[0].pageX; } this.cbs.swiping(this.diff()); } }; 

В начале метода move() мы проверяем, превысило ли расстояние, пройденное пальцем, значение допуска. Разница заключена в функции Math.abs() потому что левое движение всегда будет генерировать отрицательное значение, которое меньше любого положительного значения. Взяв его абсолютное значение, мы можем проверить расстояние как для левого, так и для правого движения. Если определено, что расстояние больше или равно значению допуска, мы считаем его проведением.

Ключевым моментом при выполнении этой работы является удаление строки this.points[0] = this.points[1]; из метода move() . Это абсолютно важно, потому что мы хотим взять ссылку с точки, где палец вступил в контакт с экраном ( touchstart ). Если мы сохраним эту строку кода, контрольная точка будет изменяться с каждым движением пальца, и мы не сможем выполнить требуемый расчет. Однако при удалении этой строки кода значение, которое возвращает diff() , также будет отличаться от предыдущего. Затем мы должны изменить определение функции обратного вызова swiping() .

Последнее изменение в классе Swiper — метод экземпляра start() . Это изменение в основном говорит о том, что каждый раз, когда палец впервые помещается на экран, флаг swipeDone в значение false, что является естественным, поскольку при первом касании экрана пальцем сгенерировать невозможно.

 Swiper.prototype.start = function (evt) { if (evt.targetTouches && evt.targetTouches.length === 1) { this.swipeDone = false; ... } }; 

Мы почти закончили с самим плагином. Изменение кода приложения для использования плагина требует смены парадигмы в том, как мы манипулируем позицией карусели, пока палец все еще тянет по экрану. Помните, что карусель должна «привязываться» к позициям, которые показывают любое изображение полностью. В результате значение позиции всегда кратно ширине каждого изображения. Таким образом, проще всего представлять позицию в процентах. Обратите внимание, что поскольку мы рассматриваем значение currPos в процентах, значения MAX_LEFT и MAX_RIGHT необходимо преобразовать в проценты.

Мы все еще хотим сохранить зеркальный эффект карусели на пальце. Для этого в adhocPos ) вводится новая переменная adhocPos . Это значение удерживает положение карусели, когда палец тянет на экране. Он использует переменную baseWidth которая установлена ​​в 330 пикселей (ширина каждого изображения в карусели). Это значение должно быть изменено, если изменяется ширина изображения в карусели.

 ... MAX_LEFT = -300, MAX_RIGHT = 0, baseWidth = 330; cb = { swiping: function (displacement) { var adhocPos = currPos / 100 * baseWidth; adhocPos += displacement; pictures.css('left', adhocPos + 'px'); }, ... } 

Значение currPos обрабатывается в процентах, которые устанавливаются в currPos ниже:

 swiped: function (direction) { currPos += (direction * 100); if (currPos < MAX_LEFT || currPos > MAX_RIGHT) { //ie exceeded limit currPos -= (direction * 100); } pictures.css('left', currPos + '%'); } 

Обратному вызову передается параметр direction который, как мы видели ранее, равен 1 или -1 . Затем это умножается на 100, чтобы преобразовать в процентное значение, прежде чем суммировать с помощью currPos . Оператор if проверяет, остается ли значение в пределах границ, чтобы карусель не прокручивалась в пустое пространство. Ранее это было сделано в swiping() . Помещая эту проверку в обратный вызов swiped() , мы получаем эффект, когда пользователь перетаскивает карусель за последнее изображение, мы видим пустое пространство, но как только палец поднимается, карусель отскакивает назад, создавая своего рода «Подпрыгивающий» эффект.

Наконец, есть обратный вызов swipeCancel() который возвращает карусель в исходное положение до начала перетаскивания.

 swipeCancel: function () { pictures.css('left', currPos + '%'); } 

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