Как стать автором
Поиск
Написать публикацию
Обновить

Kinetic ScrollBar

Время на прочтение4 мин
Количество просмотров14K
Эффект кинетической прокрутки сейчас можно встретить практически везде. Это действительно удобно при управлении пальцами или стилусом и довольно забавно при прокрутке мышкой.

В вебе такой эффект пока только приживается. Да и не так уж просто придумать, где он будет удобен… В голову приходят пожалуй лишь scroll bar’ы, которые используются для прокрутки некоторого контента, в основном картинок, внутри страницы. Для примера, можно посмотреть реализацию галереи практически на любом сайте. Согласитесь, было бы значительно интереснее, если бы ползунок не останавливался сразу, как только отпустили кнопку мыши, а продолжал бы двигаться дальше по инерции, постепенно останавливаясь…
Я попытаюсь рассмотреть процесс создания такого эффекта «кинетического» scroll bar’a. Что получилось в итоге можно посмотреть здесь

Алгоритм


Для начала, рассмотрим общий алгоритм (перетаскивание ползунка + «допрокрутка»). Он, на удивление, простой:
  • Отловить mouseDown на объекте, запомнить координаты нажатия.
  • Отслеживать mouseMove. Если был клик (пункт 1), перенести объект на новое место, в противном случае ничего не делать.
  • Замерить скорость. Достаточно просто определить dx: изменение координаты x объекта за одно событие mouseMove.
  • Отловить mouseUp. На основе последнего найденного dx, можно рассчитать некоторый импульс и найти расстояние, до которого нужно перенести объект.
  • Используя формулы затухания, анимировать перемещение объекта на нужное расстояние.

Как видно, все довольно просто. Очевидно, что подобный алгоритм универсален и подходит не только для JS…

Реализация


Для удобства можно использовать библиотеку jQuery и easing эффекты из jQuery UI.
HTML код будет следующим:
<div id="track">
  <div id="thumb"></div>
</div>

Где track – область, в которой бегает ползунок, а thumb – сам ползунок.
CSS:
#track {
  width: 500px;
  position: relative;
  display: block;
  height: 22px;
  margin: 20px;
  border: solid 1px #000;
  overflow: hidden;
}

#track #thumb {
  width: 70px;
  height: 22px;
  position: absolute;
  background-color: gray;
  left: 200px;
}

Теперь можно перейти к написанию самого скрипта. Писать я буду в обычном процедурном стиле, поскольку это учебный пример… при желании можно переписать на прототипах или оформить в виде jQuery плагина.
Введем следующие глобальные переменные:
  1. $track (jQuery объект) – область scroll bar’a
  2. $thumb (jQuery объект) – ползунок
  3. isClicked (bool) – переменная, определяющая кликнули по ползунку или нет.
  4. clickPointX (int) – x координта клика на объекте
  5. dx (int) – изменение координаты x объекта за одно событие mouseMove.
var $track = $('#track');
var $thumb = $('#thumb');        

var isClicked = false;
var clickPointX = 0;
var dx = 0;

Первым делом запретим некоторым рыжим браузерам пытаться перетаскивать наш ползунок:
$thumb.bind('dragstart',  false);

Обрабатываем mouseDown на объекте:
$thumb.mousedown( function(e) {
  // Координаты клика на объекте
  clickPointX = e.pageX - $(this).offset().left;
  isClicked = true;

  $thumb.stop(); // Останавливаем анимацию ползунка
});

Обрабатываем mouseMove, но уже не на объекте, а на всем документе
$(document).mousemove( function(e) {
  if (isClicked) {
    // Новое положение ползунка, в зависимости от текущих
    // координат мыши
    var x = (e.pageX - $track.offset().left - clickPointX);

    // Входит ли ползунок в границы области 
    if (x < -maxBorderOut) {
      x = -maxBorderOut;
    }
    if ( (x + $thumb.width()) > ($track.width() + maxBorderOut)) {
      x = $track.width() - $thumb.width() + maxBorderOut; 
    }

    // Текущее положение
    var selfLeft = parseInt($thumb.css('left'));

    $thumb.css({'left': x + 'px' }); 

    dx = x - selfLeft;
  }
});

Здесь встречается необъявленная переменная maxBorderOut, которая обозначает максимальное количество пикселей, на которое можно утащить ползунок за границы области.
И, наконец, mouseUp:
$(document).mouseup( function(e) {
  if (isClicked) {

    if (Math.abs(dx) < lapse) {
      dx = 0;
    }          

    var selfLeft = parseInt($thumb.css('left'));

    // Новое положение ползунка
    // "impulse * dx" как раз та величина, на которую необходимо доскроллить 
    var x = (selfLeft + impulse * dx);

    // Проверка, не выходит ли ползунок за границы области scroll box'a
    if (x < 0) {
      x = 0;
    }
    if ( (x + $thumb.width()) > $track.width() ) {
      x = $track.width() - $thumb.width(); 
    }

    // Сама анимация перемещения
    $thumb.stop().animate({'left': x + 'px'}, speed, 'easeOutQuart');
  }
  isClicked = false;

});

Переменная lapse определяет некоторую погрешность. То есть, если dx меньше чем эта погрешность, то анимация не происходит. Величина подбиралась на глаз, и может быть выбрана не совсем удачно.
Переменная impulse – величина некоторого импульса воздействующего на ползунок, и определяющего расстояние необходимое для перемещения. По сути, коэффициент умножающийся на dx. Подбирался так же на глаз.
Speed – скорость анимации.
Изменяя значения этих параметров, scroll bar можно настроить под конкретные нужды. При необходимости, сделать вертикальный скролл не должно составить труда.

Заключение


Здесь рассмотрена не полноценная реализация scroll bar’a, а лишь та часть, которая отвечает непосредственно за перетаскивание и «кинетическую» прокрутку. Код получился довольно простой, а эффект весьма интересный.
Использовать можно, к примеру, при реализации постраничной навигации, галереи изображений и т.п…

UPD Сделал jQuery плагин, скачать можно здесь. Как работает, можно посмотреть на примере простенькой карусели

Использовать довольно просто:
<div id="track"></div>

$('#track').kineticBar()
Теги:
Хабы:
Всего голосов 28: ↑21 и ↓7+14
Комментарии20

Публикации

Ближайшие события