Ползунки или новый взгляд на скрол из песочницы
Как я до этого дошел
Совсем недавно мне достался веб проект дизайн которого рисовал Гуров Сергей вот ссылка на его работу. Один из интересных элементов был скрол на странице каталога (он присутствует на многих страницах). Выглядел он так:

После долгих поисков, с разными запросами в поисковиках, я пришел к выводу что проще будет сделать самому.
Принцип работы
В соответствии с дизайном скрол должен перемещать товары вправо или влево с скоростью пропорциональной отклонению бегунка в самом скроле.
На чем писать?
За основу я взял свою любимую библиотеку jQuery и её разрешение jQuery UI (Draggable и необходимые для его работы Mouse, Widget, Core). Она мне наиболее симпатизировала, да и старый дизайн сайта был на ней.
Скелет
Создав простую разметку:
<div id="block-outer">
<div id="block-for-scroll">
<div id="block-for-scroll-inter">
<ul class="style-ul">
<li class="li li-n-1">li#1 inter text</li>
<li class="li li-n-2">li#2 inter text</li>
<li class="li li-n-3">li#3 inter text</li>
<li class="li li-n-4">li#4 inter text</li>
<li class="li li-n-5">li#5 inter text</li>
<li class="li li-n-6">li#6 inter text</li>
<li class="li li-n-7">li#7 inter text</li>
<li class="li li-n-8">li#8 inter text</li>
<li class="li li-n-9">li#9 inter text</li>
<li class="li li-n-10">li#10 inter text</li>
<li class="li li-n-11">li#11 inter text</li>
<li class="li li-n-12">li#12 inter text</li>
<li class="li li-n-13">li#13 inter text</li>
<li class="li li-n-14">li#14 inter text</li>
<li class="li li-n-15">li#15 inter text</li>
<li class="li li-n-1+">li#16 inter text</li>
<li class="li li-n-17">li#17 inter text</li>
<li class="li li-n-18">li#18 inter text</li>
<li class="li li-n-19">li#19 inter text</li>
<li class="li li-n-20">li#20 inter text</li>
<li class="li li-n-21">li#21 inter text</li>
<li class="li li-n-22">li#22 inter text</li>
<li class="li li-n-23">li#23 inter text</li>
<li class="li li-n-24">li#24 inter text</li>
</ul>
</div>
</div>
</div>
<div id="scroll-div">
<div id="scroll-outer">
<div id="scroll-toddler"></div>
</div>
</div>
И придав ей стилей:
*{
margin:0px;
padding:0px;
}
#block-outer{
position:relative;
height:200px;
margin:50px;
border:2px dashed blue;
overflow:hidden;
}
#block-outer #block-for-scroll{
position:absolute;
left:0px;
top:0px;
height:100%;
width:30000px;
}
#block-outer #block-for-scroll #block-for-scroll-inter{
position:absolute;
}
#block-for-scroll .style-ul{
list-style:none;
height:100%;
}
#block-for-scroll .style-ul .li{
position:relative;
float:left;
margin:5px;
height:186px;
border:2px dotted red;
width:180px;
}
#scroll-div{
position:relative;
margin:20px;
}
#scroll-div #scroll-outer{
position:relative;
width:300px;
height:20px;
margin:0 auto;
background:gray;
}
#scroll-div #scroll-outer #scroll-toddler{
position:absolute;
height:20px;
width:20px;
left:140px;
top:0px;
background:green;
cursor:pointer;
}
Получили наш прекрасный скелет для скрипта, рассказывать о том как я к нему дошел не буду, я все же не учу вас верстке. Вот скриншот скелета:

Скрипт
Вот эта часть то и самая интересная. Подключив jQuery и jQuery UI начал объявлять переменные и привязывать из к скелету:
$(document).ready(function(){
//индификатор интервала анимации
var scrollIntervalVar;
//отклонение ползунка (интервал от -1 до 1)
var scrollPercentSpeed = 0;
//скорость перемещения
var scrollSpeed = 10;
//инверсия скролла
var scrollRevert = false;
//id блока за который будем перемещать (ползунок)
var idScrollToddler = "scroll-toddler";
//id контейнера для этого же блока (внутри него будет перемещатся ползунок)
var idScrollConteiner = "scroll-outer";
//этот блок имитирует переремещения скрола
var idSlideDiv = "block-for-scroll";
//это наша рамка внутри которой всё будет происходить
var idSlideOuterDiv = "block-outer";
//ну и конешно же сам блок внутри которого само содержимое
var idSlideWidthDiv = "block-for-scroll-inter";
//ось ползунка (вещь пока не нужная она нам понадобится в следующих постах)
var scrollToddlerAxis = "x";
});
Определив нужные переменные принялся к вычислению и заданию стартового положения ползунка:
$(document).ready(function(){
//индификатор интервала анимации
var scrollIntervalVar;
//отклонение ползунка (интервал от -1 до 1)
var scrollPercentSpeed = 0;
//скорость перемещения
var scrollSpeed = 10;
//инверсия скролла
var scrollRevert = false;
//id блока за который будем перемещать (ползунок)
var idScrollToddler = "scroll-toddler";
//id контейнера бля этого же блока (внутри него будет перемещатся ползунок)
var idScrollConteiner = "scroll-outer";
//этот блок имитирует переремещения скрола
var idSlideDiv = "block-for-scroll";
//это наша рамка внутри которой всё будет происходить
var idSlideOuterDiv = "block-outer";
//ну и конешно же сам блок внутри которого само содержимое
var idSlideWidthDiv = "block-for-scroll-inter";
//ось ползунка (вещь пока не нужная она нам понадобится в следующих постах)
var scrollToddlerAxis = "x";
//Вычеслим центр самого ползунка
//он нам пригодится для центрирования положения относительно миши
var centerToddler = {'x':$('#'+idScrollToddler).outerWidth(true)/2,'y':$('#'+idScrollToddler).outerHeight(true)/2};
//Ну и конешно зададим его для него
document.getElementById(idScrollToddler).style.left = centerToddlerPosition+'px';
//Возьмем ширину конетейнера для ползунка
var widthConteiner = $('#'+idScrollConteiner).width();
//Возьмем ширину ползунка
var widthToddler = $('#'+idScrollToddler).width();
//Вычеслим css left для центрального положения ползунка
var centerToddlerPosition = (widthConteiner-widthToddler)/2;
//Возьмем ширину внутреностей нашего скрола
var widthSlideInterDiv = $('#'+idSlideWidthDiv).outerWidth(true);
//Возьмем ширину нашего скрола
var widthSlideOuterDiv = $('#'+idSlideOuterDiv).width();
//Вычеслим минимальное значение left для скрола
var minLeftSlideDiv = widthSlideOuterDiv - widthSlideInterDiv;
//И зададим максимальное
var maxLeftSlideDiv = 0;
});
Продолжаем в том же духе, и заставим ползунок перемещается с помощью перетаскивания мыши, именно для этого было подключено расширение jQuery UI. И сразу же функции для аминирования самого скрола:
//Делаем наш ползунок перетаскиваемым
$('#'+idScrollToddler).draggable({
//Парамер отчечающий за положение курсора относительно блока
//Зададим центральное положение для ползунка
//Эти данные будут равны центру самого ползунка который мы уже определили рание
cursorAt: {
top: centerToddler.y,
left: centerToddler.x
},
//Параметр который позволит нам возвращасть ползунок
//в центральное положение после перемещений
revert: true,
//Ось по которой будет перемещатся ползунок
axis: scrollToddlerAxis,
//Блок - контейнер, внутри которого это всё будет происходить
containment: '#'+idScrollConteiner,
//Функция для события начала перетаскивания
start: function() {
//Сразу же создадим интервал для анимирования перемещений
scrollIntervalVar = setInterval(function(){
//несложными математическими функциями определим отклонение ползунка
scrollPercentSpeed = ( $('#'+idScrollToddler).position().left - centerToddlerPosition ) / centerToddlerPosition;
//получим данные о текощем положении скрола
var thisLeft = $('#'+idSlideDiv).position().left;
//Вычеслим новое положение left
//Положение бует изментся относительно положения ползунка умноженого на скорость
//Скорость была указана нами в начале скрипта
//Также применяется scrollRevert (для инверсии)
if(scrollRevert){
var newLeft = thisLeft + scrollSpeed * scrollPercentSpeed;
}else{
var newLeft = thisLeft - scrollSpeed * scrollPercentSpeed;
}
//Чтобы наш скрол имел начало и конец
//Сравним новое положение с граничными положениями (min&max)
//И в случае выхода за них задам новое положение
//Которое будет равно min или max соответственно
if( newLeft < minLeftSlideDiv ) newLeft = minLeftSlideDiv;
if( newLeft > maxLeftSlideDiv ) newLeft = maxLeftSlideDiv;
//Ну и конешно же зададим самому обекту новое положение
document.getElementById(idSlideDiv).style.left = newLeft+'px';
},13);
},
//Функция для события возврата ползунка после отжимания мишки, в нашем случае.
stop: function() {
//Ползунок будет иметь центральное положение то и отклонение тоже должно быть равно 0
//Зададим ему 0 навсякий случай
scrollPercentSpeed = 0;
//Ну и удалим наш интервал, зачем мучать браузер лишними процесами
clearInterval(scrollIntervalVar);
}
});
Пока не забыл, время для интервала выбрал именно 13 ( его кстати использует и jQuery для .animate() ).
Итоги
В результате наш ползунок заработал. Посмотреть исходный код можно в архиве тут, а также проверить его работу тут
P.S. Вскоре опубликую плагин для jQuery с полным функционалом.
P.S. 2 Очень хочу услышать критику об моем хабрапосте и самом скрипте
UPD: jQuery Plugin — Scroll Sliders или Ползунки beta



комментарии (76)