11 ответов:
попробуй такое плавная прокрутка демо, или алгоритм, как:
- получить текущее верхнее местоположение с помощью
self.pageYOffset- получить положение элемента до тех пор, где вы хотите, чтобы прокрутить:
element.offsetTop- сделайте цикл for, чтобы добраться туда, что будет довольно быстро или использовать таймер, чтобы сделать плавную прокрутку до этой позиции с помощью
window.scrollTo
см. также другой популярный ответ для этого вопрос.
исходный код Эндрю Джонсона:
function currentYPosition() { // Firefox, Chrome, Opera, Safari if (self.pageYOffset) return self.pageYOffset; // Internet Explorer 6 - standards mode if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; // Internet Explorer 6, 7 and 8 if (document.body.scrollTop) return document.body.scrollTop; return 0; } function elmYPosition(eID) { var elm = document.getElementById(eID); var y = elm.offsetTop; var node = elm; while (node.offsetParent && node.offsetParent != document.body) { node = node.offsetParent; y += node.offsetTop; } return y; } function smoothScroll(eID) { var startY = currentYPosition(); var stopY = elmYPosition(eID); var distance = stopY > startY ? stopY - startY : startY - stopY; if (distance < 100) { scrollTo(0, stopY); return; } var speed = Math.round(distance / 100); if (speed >= 20) speed = 20; var step = Math.round(distance / 25); var leapY = stopY > startY ? startY + step : startY - step; var timer = 0; if (stopY > startY) { for ( var i=startY; i<stopY; i+=step ) { setTimeout("window.scrollTo(0, "+leapY+")", timer * speed); leapY += step; if (leapY > stopY) leapY = stopY; timer++; } return; } for ( var i=startY; i>stopY; i-=step ) { setTimeout("window.scrollTo(0, "+leapY+")", timer * speed); leapY -= step; if (leapY < stopY) leapY = stopY; timer++; } }
обзоры ссылки:
редактировать: этот ответ был написан в 2013 году. Пожалуйста, проверьте комментарий Кристиана Трейна ниже о requestAnimationFrame
Я сделал это. Приведенный ниже код не зависит от какой-либо структуры.
ограничение: активный якорь не записывается в url.
версия кода : 1.0 | Github:https://github.com/Yappli/smooth-scroll
(function() // Code in a function to create an isolate scope { var speed = 500; var moving_frequency = 15; // Affects performance ! var links = document.getElementsByTagName('a'); var href; for(var i=0; i<links.length; i++) { href = (links[i].attributes.href === undefined) ? null : links[i].attributes.href.nodeValue.toString(); if(href !== null && href.length > 1 && href.substr(0, 1) == '#') { links[i].onclick = function() { var element; var href = this.attributes.href.nodeValue.toString(); if(element = document.getElementById(href.substr(1))) { var hop_count = speed/moving_frequency var getScrollTopDocumentAtBegin = getScrollTopDocument(); var gap = (getScrollTopElement(element) - getScrollTopDocumentAtBegin) / hop_count; for(var i = 1; i <= hop_count; i++) { (function() { var hop_top_position = gap*i; setTimeout(function(){ window.scrollTo(0, hop_top_position + getScrollTopDocumentAtBegin); }, moving_frequency*i); })(); } } return false; }; } } var getScrollTopElement = function (e) { var top = 0; while (e.offsetParent != undefined && e.offsetParent != null) { top += e.offsetTop + (e.clientTop != null ? e.clientTop : 0); e = e.offsetParent; } return top; }; var getScrollTopDocument = function() { return document.documentElement.scrollTop + document.body.scrollTop; }; })();
алгоритм
прокрутка элемента требует изменения его
scrollTopценность с течением времени. Для данного момента времени вычислите новыйscrollTopзначение. Чтобы анимировать плавно, интерполируйте с помощью алгоритм плавного шага.вычислить
scrollTopследующим образом:var point = smooth_step(start_time, end_time, now); var scrollTop = Math.round(start_top + (distance * point));где:
start_timeвремя начала анимации;end_timeкогда анимация закончится(start_time + duration);start_top- этоscrollTopзначение в начале; иdistanceразница между желаемым конечным значением и начальным значением(target - start_top).надежное решение должно обнаруживать, когда анимация прерывается, и многое другое. Читайте мой пост о плавная прокрутка без jQuery для сведения.
демо
посмотреть JSFiddle.
реализация
код:
/** Smoothly scroll element to the given target (element.scrollTop) for the given duration Returns a promise that's fulfilled when done, or rejected if interrupted */ var smooth_scroll_to = function(element, target, duration) { target = Math.round(target); duration = Math.round(duration); if (duration < 0) { return Promise.reject("bad duration"); } if (duration === 0) { element.scrollTop = target; return Promise.resolve(); } var start_time = Date.now(); var end_time = start_time + duration; var start_top = element.scrollTop; var distance = target - start_top; // based on http://en.wikipedia.org/wiki/Smoothstep var smooth_step = function(start, end, point) { if(point <= start) { return 0; } if(point >= end) { return 1; } var x = (point - start) / (end - start); // interpolation return x*x*(3 - 2*x); } return new Promise(function(resolve, reject) { // This is to keep track of where the element's scrollTop is // supposed to be, based on what we're doing var previous_top = element.scrollTop; // This is like a think function from a game loop var scroll_frame = function() { if(element.scrollTop != previous_top) { reject("interrupted"); return; } // set the scrollTop for this frame var now = Date.now(); var point = smooth_step(start_time, end_time, now); var frameTop = Math.round(start_top + (distance * point)); element.scrollTop = frameTop; // check if we're done! if(now >= end_time) { resolve(); return; } // If we were supposed to scroll but didn't, then we // probably hit the limit, so consider it done; not // interrupted. if(element.scrollTop === previous_top && element.scrollTop !== frameTop) { resolve(); return; } previous_top = element.scrollTop; // schedule next frame for execution setTimeout(scroll_frame, 0); } // boostrap the animation process setTimeout(scroll_frame, 0); }); }
собственный браузер плавная прокрутка в JavaScript выглядит так:
// Scroll to specific values // scrollTo is the same window.scroll({ top: 2500, left: 0, behavior: 'smooth' }); // Scroll certain amounts from current position window.scrollBy({ top: 100, // could be negative value left: 0, behavior: 'smooth' }); // Scroll to a certain element document.querySelector('.hello').scrollIntoView({ behavior: 'smooth' });
Я сделал пример без jQuery здесь:http://codepen.io/sorinnn/pen/ovzdq
/** by Nemes Ioan Sorin - not an jQuery big fan therefore this script is for those who love the old clean coding style @id = the id of the element who need to bring into view Note : this demo scrolls about 12.700 pixels from Link1 to Link3 */ (function() { window.setTimeout = window.setTimeout; // })(); var smoothScr = { iterr : 30, // set timeout miliseconds ..decreased with 1ms for each iteration tm : null, //timeout local variable stopShow: function() { clearTimeout(this.tm); // stopp the timeout this.iterr = 30; // reset milisec iterator to original value }, getRealTop : function (el) // helper function instead of jQuery { var elm = el; var realTop = 0; do { realTop += elm.offsetTop; elm = elm.offsetParent; } while(elm); return realTop; }, getPageScroll : function() // helper function instead of jQuery { var pgYoff = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop; return pgYoff; }, anim : function (id) // the main func { this.stopShow(); // for click on another button or link var eOff, pOff, tOff, scrVal, pos, dir, step; eOff = document.getElementById(id).offsetTop; // element offsetTop tOff = this.getRealTop(document.getElementById(id).parentNode); // terminus point pOff = this.getPageScroll(); // page offsetTop if (pOff === null || isNaN(pOff) || pOff === 'undefined') pOff = 0; scrVal = eOff - pOff; // actual scroll value; if (scrVal > tOff) { pos = (eOff - tOff - pOff); dir = 1; } if (scrVal < tOff) { pos = (pOff + tOff) - eOff; dir = -1; } if(scrVal !== tOff) { step = ~~((pos / 4) +1) * dir; if(this.iterr > 1) this.iterr -= 1; else this.itter = 0; // decrease the timeout timer value but not below 0 window.scrollBy(0, step); this.tm = window.setTimeout(function() { smoothScr.anim(id); }, this.iterr); } if(scrVal === tOff) { this.stopShow(); // reset function values return; } } }
недавно я решил решить эту проблему в ситуации, когда jQuery не был вариантом, поэтому я регистрирую свое решение здесь только для потомков.
var scroll = (function() { var elementPosition = function(a) { return function() { return a.getBoundingClientRect().top; }; }; var scrolling = function( elementID ) { var el = document.getElementById( elementID ), elPos = elementPosition( el ), duration = 400, increment = Math.round( Math.abs( elPos() )/40 ), time = Math.round( duration/increment ), prev = 0, E; function scroller() { E = elPos(); if (E === prev) { return; } else { prev = E; } increment = (E > -20 && E < 20) ? ((E > - 5 && E < 5) ? 1 : 5) : increment; if (E > 1 || E < -1) { if (E < 0) { window.scrollBy( 0,-increment ); } else { window.scrollBy( 0,increment ); } setTimeout(scroller, time); } else { el.scrollTo( 0,0 ); } } scroller(); }; return { To: scrolling } })(); /* usage */ scroll.To('elementID');The
Я сделал что-то вроде этого. Я понятия не имею, работает ли он в IE8. Протестировано в IE9, Mozilla, Chrome, Edge.
function scroll(toElement, speed) { var windowObject = window; var windowPos = windowObject.pageYOffset; var pointer = toElement.getAttribute('href').slice(1); var elem = document.getElementById(pointer); var elemOffset = elem.offsetTop; var counter = setInterval(function() { windowPos; if (windowPos > elemOffset) { // from bottom to top windowObject.scrollTo(0, windowPos); windowPos -= speed; if (windowPos <= elemOffset) { // scrolling until elemOffset is higher than scrollbar position, cancel interval and set scrollbar to element position clearInterval(counter); windowObject.scrollTo(0, elemOffset); } } else { // from top to bottom windowObject.scrollTo(0, windowPos); windowPos += speed; if (windowPos >= elemOffset) { // scroll until scrollbar is lower than element, cancel interval and set scrollbar to element position clearInterval(counter); windowObject.scrollTo(0, elemOffset); } } }, 1); } //call example var navPointer = document.getElementsByClassName('nav__anchor'); for (i = 0; i < navPointer.length; i++) { navPointer[i].addEventListener('click', function(e) { scroll(this, 18); e.preventDefault(); }); }описание
pointer- получить элемент и chceck, если он имеет атрибут "href", если да, избавьтесь от "#"elem- переменная указателя без "#"elemOffset-смещение элемента "scroll to" от верхней части страницы
современные браузеры поддерживают свойство CSS "scroll-behavior: smooth". Итак, нам даже не нужен никакой Javascript для этого. Просто добавьте это в элемент body и используйте обычные якоря и ссылки. прокрутка-поведение MDN docs
можно использовать
document.querySelector('your-element').scrollIntoView({behavior: 'smooth'});Если вы хотите прокрутить верхнюю часть страницы, вы можете просто поместить пустой элемент в верхнюю часть и плавно прокрутить его.
вы можете использовать цикл for с окном.scrollTo и setTimeout для плавной прокрутки с помощью простого Javascript. Чтобы перейти к элементу с помощью my
scrollToSmoothlyфункция:scrollToSmoothly(elem.offsetTop)(Еслиelemявляется элементом DOM). Вы можете использовать это для плавной прокрутки до любой позиции y в документе.function scrollToSmoothly(pos, time){ /*Time is only applicable for scrolling upwards*/ /*Code written by hev1*/ /*pos is the y-position to scroll to (in pixels)*/ if(isNaN(pos)){ throw "Position must be a number"; } if(pos<0){ throw "Position can not be negative"; } var currentPos = window.scrollY||window.screenTop; if(currentPos<pos){ var t = 10; for(let i = currentPos; i <= pos; i+=10){ t+=10; setTimeout(function(){ window.scrollTo(0, i); }, t/2); } } else { time = time || 2; var i = currentPos; var x; x = setInterval(function(){ window.scrollTo(0, i); i -= 10; if(i<=pos){ clearInterval(x); } }, time); } }демо:
<button onClick="scrollToDiv()">Scroll To Element</button> <div style="margin: 1000px 0px; text-align: center;">Div element<p/> <button onClick="scrollToSmoothly(Number(0))">Scroll back to top</button> </div> <script> function scrollToSmoothly(pos, time){ /*Time is only applicable for scrolling upwards*/ /*Code written by hev1*/ /*pos is the y-position to scroll to (in pixels)*/ if(isNaN(pos)){ throw "Position must be a number"; } if(pos<0){ throw "Position can not be negative"; } var currentPos = window.scrollY||window.screenTop; if(currentPos<pos){ var t = 10; for(let i = currentPos; i <= pos; i+=10){ t+=10; setTimeout(function(){ window.scrollTo(0, i); }, t/2); } } else { time = time || 2; var i = currentPos; var x; x = setInterval(function(){ window.scrollTo(0, i); i -= 10; if(i<=pos){ clearInterval(x); } }, time); } } function scrollToDiv(){ var elem = document.querySelector("div"); scrollToSmoothly(elem.offsetTop); } </script>
<script> var set = 0; function animatescroll(x, y) { if (set == 0) { var val72 = 0; var val73 = 0; var setin = 0; set = 1; var interval = setInterval(function() { if (setin == 0) { val72++; val73 += x / 1000; if (val72 == 1000) { val73 = 0; interval = clearInterval(interval); } document.getElementById(y).scrollTop = val73; } }, 1); } } </script>x = scrollTop
y = идентификатор элемента div, который используется для прокрутки
Примечание: Для создания тела для прокрутки дайте телу идентификатор.
Comments