Плавный scroll элементов на javascript
Я давно уж ничего не писал, да и мыслей, достойных публикации не возникало. Но забрасывать блог не хотелось, поэтому я решил написать о ещё одной небольшой проблемке в javascript. Сегодня я покажу, как сделать плавный анимированный скрол любого элемента.
Анимацию я сделал с помощью своей любимой анимационной функции, которую использую практически для всех операций подобного рода. На этот раз все функции и переменные убраны в объект scroll - просто для того чтобы создать закрытый неймспейс и случайно не пересечься с другими переменными.
Собственно о скролле: скролл бывает разный. Есть скролл различных дом элементов, например дивов с параметром overflow:scroll или текстовых полей. Он реализуется с помощью присвоения значений scrollTop и scrollLeft. Но есть и другой вид скролла. Это скролл окна браузера - объекта window. Он осуществляется специальным методом scrollTo().
Текущее положени скролла как у окна браузера так и у различных элементов получается достаточно легко, нужно только учесть, что в режиме соответствия стандартам браузер выдает информацию о скролле окна браузера только при обращении к documentElement а не к document.body. На этом сложности заканчиваются.
От слов к делу, вот функция, осуществляющая скролл как в элементах так и в окне браузера. Функция проверена во всех версиях осла ну и соответственно во всех остальных популярных браузерах. Ошибок нет. выполняется ровно. Вызывается вот так: Пример работы именно этой функции я приводить не буду, но так как аналогичный способ прокрутки используется на моем сайте, я просто приведу в пример пару ссылок: прокрутить страницу наверх (скорость 300мс) и прокрутить страницу на 600px (скорость 500мс, alert по завершении).
+ за пост в карму на форуме =)
Анимацию я сделал с помощью своей любимой анимационной функции, которую использую практически для всех операций подобного рода. На этот раз все функции и переменные убраны в объект scroll - просто для того чтобы создать закрытый неймспейс и случайно не пересечься с другими переменными.
Собственно о скролле: скролл бывает разный. Есть скролл различных дом элементов, например дивов с параметром overflow:scroll или текстовых полей. Он реализуется с помощью присвоения значений scrollTop и scrollLeft. Но есть и другой вид скролла. Это скролл окна браузера - объекта window. Он осуществляется специальным методом scrollTo().
Текущее положени скролла как у окна браузера так и у различных элементов получается достаточно легко, нужно только учесть, что в режиме соответствия стандартам браузер выдает информацию о скролле окна браузера только при обращении к documentElement а не к document.body. На этом сложности заканчиваются.
От слов к делу, вот функция, осуществляющая скролл как в элементах так и в окне браузера.
Code
<script type='text/javascript'>
Scroll = {
sL:function(o){return o!=window?o.scrollLeft:document.body.scrollLeft||document.documentElement.scrollLeft},
sT:function(o){return o!=window?o.scrollTop:document.body.scrollTop||document.documentElement.scrollTop},
anim:function(p){function d(p){return Math.pow(p,3)};if(p<0.5){return d(2*p)/2;}else{return (2-d(2*(1-p)))/2;}}, // рассчет анимации
animator:[], /* массив с анимируемыми объектами */
anielems:0, /* счетчик анимируемых объектов */
to: function(obj,values,time,callback){
// перебираем параметры и значения
for(key in values){anima(key,values[key])}
function anima(param,to){
// проверяем и останавливаем предыдущие анимации
for(key in Scroll.animator){if(Scroll.animator[key].o==obj&&Scroll.animator[key].p==param){clearInterval(Scroll.animator[key].timer)}}
var aID=Scroll.anielems,
result,
now,
progress,
w=obj==window?1:0,
param=param=='x'?1:0,
from=param?Scroll.sL(obj):Scroll.sT(obj);
Scroll.animator[aID] = {
start: new Date().getTime(),
timer: setInterval(function(){
now=(new Date().getTime())-Scroll.animator[aID].start;
progress=now/time;
result=(to-from)*Scroll.anim(progress)+from;
if(param){
if(w){window.scrollTo(result,Scroll.sT(obj))}
else{obj.scrollLeft=result}
}else{
if(w){window.scrollTo(Scroll.sL(obj),result)}
else{obj.scrollTop=result}
}
if(progress>=1){
clearInterval(Scroll.animator[aID].timer);
if(param){
if(w){window.scrollTo(to,Scroll.sT(obj))}
else{obj.scrollLeft=to}
}else{
if(w){window.scrollTo(Scroll.sL(obj),to)}
else{obj.scrollTop=to}
}
if(callback){callback()}
}
},10)
}
Scroll.anielems++;
}
}
};
</script>
Scroll = {
sL:function(o){return o!=window?o.scrollLeft:document.body.scrollLeft||document.documentElement.scrollLeft},
sT:function(o){return o!=window?o.scrollTop:document.body.scrollTop||document.documentElement.scrollTop},
anim:function(p){function d(p){return Math.pow(p,3)};if(p<0.5){return d(2*p)/2;}else{return (2-d(2*(1-p)))/2;}}, // рассчет анимации
animator:[], /* массив с анимируемыми объектами */
anielems:0, /* счетчик анимируемых объектов */
to: function(obj,values,time,callback){
// перебираем параметры и значения
for(key in values){anima(key,values[key])}
function anima(param,to){
// проверяем и останавливаем предыдущие анимации
for(key in Scroll.animator){if(Scroll.animator[key].o==obj&&Scroll.animator[key].p==param){clearInterval(Scroll.animator[key].timer)}}
var aID=Scroll.anielems,
result,
now,
progress,
w=obj==window?1:0,
param=param=='x'?1:0,
from=param?Scroll.sL(obj):Scroll.sT(obj);
Scroll.animator[aID] = {
start: new Date().getTime(),
timer: setInterval(function(){
now=(new Date().getTime())-Scroll.animator[aID].start;
progress=now/time;
result=(to-from)*Scroll.anim(progress)+from;
if(param){
if(w){window.scrollTo(result,Scroll.sT(obj))}
else{obj.scrollLeft=result}
}else{
if(w){window.scrollTo(Scroll.sL(obj),result)}
else{obj.scrollTop=result}
}
if(progress>=1){
clearInterval(Scroll.animator[aID].timer);
if(param){
if(w){window.scrollTo(to,Scroll.sT(obj))}
else{obj.scrollLeft=to}
}else{
if(w){window.scrollTo(Scroll.sL(obj),to)}
else{obj.scrollTop=to}
}
if(callback){callback()}
}
},10)
}
Scroll.anielems++;
}
}
};
</script>
Code
<script type='text/javascript'>
Scroll.to(window,{'x':500,'y':300},400);
// прокрутит окно браузера на заданное количество
// пикселей по горизонтали и вертикали за 400 миллисекунд
Scroll.to(mydiv,{'y':200},1000,function(){ alert('') });
// прокрутит по вертикали див блок за 1000мс и выдаст алерт
// ну и так далее
</script>
Scroll.to(window,{'x':500,'y':300},400);
// прокрутит окно браузера на заданное количество
// пикселей по горизонтали и вертикали за 400 миллисекунд
Scroll.to(mydiv,{'y':200},1000,function(){ alert('') });
// прокрутит по вертикали див блок за 1000мс и выдаст алерт
// ну и так далее
</script>
+ за пост в карму на форуме =)
29, 8, 9515
№8
Черемушкин Илья
А зачем ты все в объект выделил? Почему не пользоваться обычными переменными?
Ответ: Чтобы глобальную область видимости не занимать.
№7
Aleko
[sayto]Иван0[/sayto], аааа, да, спасибо.
№6
Aleko
[sayto]Иван0[/sayto], что скачет? O_o
№5
Иван0
Интересно на форуме скачет
№4
Иван
[sayto]Aleko[/sayto], +1 :)
№3
DSC
Прикольный скрипт, спасибки!)
№2
Артем
Спасибо, отличное решение
№1
neio
Хм... утащил себе