Скролінг контенту методом торкання і перетягування на jQuery

Hello, jQuery, again!

Завдання даного плагіна — скролінг контенту за допомогою торкання і перетягування.

Використовувані події mousedown/move/up. За замовчуванням ця ланцюжок подій виділяє вміст в межах дотику.

Реалізація — до болю знайоме overflow:hidden, обгортання вмісту елемента і переміщення контенту всередині.

Невирішені проблеми
1. Іноді, на межі між перетином нижнього краю п'ятикратним уповільненням, контент зсувається вгору на певний інтервал. Примітно, що при зворотному русі (в момент перетину цієї риси) контент повертається на своє місце (зсувається вниз).

Сподіваюся, для когось ця стаття виявиться корисною і знайде своє застосування.
Вэлком в коментарі, чекаю на ваші думки, ваш конструктив і негатив, все, що спрямовано на покращення даного коду!

Випробувальний стенд на jsFiddle (52 рядка некомментированного коду).

Почнемо з розмітки. У нас є блок з контентом:

<div id="content">
<h2>Touch and drag content</h2>
<p>Lorem ipsum dolor sit amet...</p>
</div>

#content {
position:absolute;
left:50px;
top:50px;
width:500px;
height:350px;
text-align:justify;
}

Далі — докладне коментування кожної дії.

// обертаємо плагін в анонімну функцію
(function($){
// пишемо функцію з ім'ям нашого плагіна
$.fn.touchanddrag = function(){
// обертаємо вміст нашого елемента в дочірній елемент, який і будемо переміщати
// вихідний елемент зберігає свою розмітку і властивості, задані йому в css
this.wrapInner('<div>');
// вихідний елемент тепер став контейнером, а новий елемент - обгортка для його даних
// тобто вихідний елемент (box) - батько, а новий елемент (data) - дочірній
var box = this,
data = this.children();
// ховаємо смугу прокручування
box.css({overflow:'hidden'});
// позиціонуємо елемент data
data.css({position:'absolute',cursor:'default'});
// подія торкання на елементі
data.mousedown(function(e){
// висота елементів для подальших обчислень
var hgtBox = box.height(),
hgtData = data.height();
// перевіряємо, чи достатньо контенту для прокручування
if (hgtData>hgtBox) {
// позиція торкання
var posTap = e.pageY,
// позиція елемента data щодо елемента box
posData = data.position().top,
posShift,
// подія ковзання в межах документа
mouseMove = function(e){
// перевіряємо, чи натиснута чи ще кнопка миші
if (e.which==1){
// відстань, пройдена щодо першого дотику
posShift = e.pageY-posTap;
// якщо прокрутили контент вище верхнього краю
if (data.position().top>0){
// переміщаємо контент, але в 5 разів повільніше
// фрагмент імітації кінетичної прокручування
data.css({top:(posData+posShift)/5});
// якщо прокрутили контент нижче нижнього краю
} else if ((data.position().top+hgtData)<hgtBox){
// сповільнюємо переміщення в п'ять разів
data.css({top:(hgtBox-hgtData)+(posShift/5)});
// прокрутка контенту в межах видимості батьків
} else {
// додаємо різницю до попередніх координатами
data.css({top:posData+posShift});
}
} else {
mouseUp();
}
},
// відпускання подія
mouseUp = function(){
// скасовуємо моніторинг перетягування і блокування виділення
$(document).off('mousemove',mouseMove).off('mouseup',mouseUp);
$(document).off('mousedown',selection);
// повертаємо вигляд курсору
data.css({cursor:'default'});
// якщо після прокручування контент виявився вище верхнього краю 
if (data.position().top>0){
// плавно повертаємо його в крайню верхню позицію
// фрагмент імітації кінетичної прокручування
data.animate({top:0},250);
// якщо після прокручування контент виявився нижче нижнього краю
} else if ((data.position().top+hgtData)<hgtBox) {
// плавно повертаємо його в крайню нижню позицію
data.animate({top:hgtBox-hgtData},250);
}
},
// зняття виділення перетягування вмісту
selection = function(){
if (window.getSelection){window.getSelection().removeAllRanges()}
else {document.selection.empty()}
return false;
};
// змінюємо вигляд курсору на час перетягування
data.css({cursor:'move'});
// ініціалізуємо моніторинг перетягування і блокування виділення
$(document).on('mousedown',selection).on('mousemove',mouseMove);
$(document).on('mouseup',mouseUp).on('contextmenu',mouseUp);
$(window).on('blur',mouseUp);
}
});
return this;
};
})(jQuery);

Викликаємо плагін:

$('#content').touchanddrag();

UPD 1 — виправлений баг, при якому контент продовжував скроллиться при відпусканні кнопки миші за межами кадру. Додана перевірка

if (e.which==1)

UPD 2 — в css об'єктах прибрав екранування ключів

data.css({cursor:'move'})

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.