Estoy codificando una página en la que solo quiero usar código JavaScript sin formato para la interfaz de usuario sin ninguna interferencia de complementos o marcos.
Y ahora estoy luchando por encontrar una manera de desplazarme por la página sin problemas sin jQuery.
javascript
html
Paolo Forgia
fuente
fuente
Respuestas:
Pruebe esta demostración de desplazamiento suave o un algoritmo como:
self.pageYOffset
element.offsetTop
window.scrollTo
Vea también la otra respuesta popular a esta pregunta.
Código original de Andrew Johnson:
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++; } }
Enlaces relacionados:
fuente
El desplazamiento suave del navegador nativo en JavaScript es así:
// scroll to specific values, // same as window.scroll() method. // for scrolling a particular distance, use window.scrollBy(). window.scroll({ top: 2500, left: 0, behavior: 'smooth' }); // scroll certain amounts from current position window.scrollBy({ top: 100, // negative value acceptable left: 0, behavior: 'smooth' }); // scroll to a certain element document.querySelector('.hello').scrollIntoView({ behavior: 'smooth' });
fuente
speed
opción. La velocidad de desplazamiento actual es demasiado lenta para el flujo.editar: esta respuesta se escribió en 2013. Por favor, consulte el comentario de Cristian Traìna a continuación sobre requestAnimationFrame
Lo hice. El siguiente código no depende de ningún marco.
Limitación: el ancla activa no está escrita en la URL.
Versión del código: 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; }; })();
fuente
var _updateURL = function ( anchor, url ) { if ( (url === true || url === 'true') && history.pushState ) { history.pushState( {pos:anchor.id}, '', anchor ); } };
(a través de Smooth Scroll js de Chris Fernandi ) para escribir el ancla a la URL. ¡Es bueno ver a la gente haciendo esto en lugar de simplemente "usar JQuery"! Para que conste, los:target
selectores también son una buena solución.Algoritmo
El desplazamiento de un elemento requiere cambiar su
scrollTop
valor con el tiempo. Para un momento dado, calcula un nuevoscrollTop
valor. Para animar sin problemas, interpole usando un algoritmo de pasos suaves .Calcule
scrollTop
como sigue:var point = smooth_step(start_time, end_time, now); var scrollTop = Math.round(start_top + (distance * point));
Dónde:
start_time
es el momento en que comenzó la animación;end_time
es cuando terminará la animación(start_time + duration)
;start_top
es elscrollTop
valor al principio; ydistance
es la diferencia entre el valor final deseado y el valor inicial(target - start_top)
.Una solución robusta debería detectar cuándo se interrumpe la animación, y más. Lea mi publicación sobre Smooth Scrolling sin jQuery para obtener más detalles.
Manifestación
Vea el JSFiddle .
Implementación
El código:
/** 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); }); }
fuente
pageYOffset
yscrollTo()
enelement
lugar descrollTop
.He hecho un ejemplo sin jQuery aquí: 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; } } }
fuente
window.setTimeout = window.setTimeout;
Los navegadores modernos admiten la propiedad CSS "scroll-behavior: smooth". Entonces, ni siquiera necesitamos ningún Javascript para esto. Solo agregue esto al elemento del cuerpo y use anclajes y enlaces habituales. documentos MDN de comportamiento de desplazamiento
fuente
Recientemente me propuse resolver este problema en una situación en la que jQuery no era una opción, así que estoy registrando mi solución aquí solo para la posteridad.
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');
La
scroll()
función usa el patrón de módulo revelador para pasar la identificación del elemento de destino a suscrolling()
función, viascroll.To('id')
, que establece los valores utilizados por lascroller()
función.Descompostura
En
scrolling()
:el
: el objeto DOM de destinoelPos
: devuelve una función a través de laelememtPosition()
cual proporciona la posición del elemento de destino en relación con la parte superior de la página cada vez que se llama.duration
: tiempo de transición en milisegundos.increment
: divide la posición inicial del elemento de destino en 40 pasos.time
: establece el tiempo de cada paso.prev
: la posición anterior del elemento de destino enscroller()
.E
: mantiene la posición del elemento de destino enscroller()
.El trabajo real lo realiza la
scroller()
función que continúa llamándose a sí misma (viasetTimeout()
) hasta que el elemento de destino está en la parte superior de la página o la página no puede desplazarse más.Cada vez que
scroller()
se llama, verifica la posición actual del elemento de destino (mantenido en la variableE
) y si eso es> 1
OR< -1
y si la página todavía se puede desplazar, cambia la ventana enincrement
píxeles, hacia arriba o hacia abajo, dependiendo de siE
es un valor positivo o negativo. CuandoE
no es> 1
OR< -1
oE
===prev
la función se detiene. Agregué elDOMElement.scrollTo()
método al finalizar solo para asegurarme de que el elemento de destino golpeara en la parte superior de la ventana (¡no es que te des cuenta de que está fuera por una fracción de píxel!)La
if
declaración en la línea 2 descroller()
verifica si la página se está desplazando (en los casos en los que el objetivo podría estar hacia la parte inferior de la página y la página no puede desplazarse más) comprobandoE
su posición anterior (prev
).La condición ternaria por debajo reduce el
increment
valor a medida que seE
acerca a cero. Esto evita que la página se sobrepase en un sentido y luego rebote para sobrepasar en el otro, y luego rebote para sobrepasar al otro de nuevo, estilo ping-pong, hasta el infinito y más allá.Si su página tiene más de c.4000px de altura, es posible que desee aumentar los valores en la primera condición de la expresión ternaria (aquí en +/- 20) y / o el divisor que establece el
increment
valor (aquí en 40).Jugar con
duration
, el divisor que se estableceincrement
y los valores en la condición ternaria descroller()
debería permitirle adaptar la función para que se adapte a su página.JSFiddle
Nota: Probado en versiones actualizadas de Firefox y Chrome en Lubuntu, y Firefox, Chrome e IE en Windows8.
fuente
También puede utilizar la propiedad de comportamiento de desplazamiento . por ejemplo, agregue la siguiente línea a su css
html{ scroll-behavior:smooth; }
y esto dará como resultado una característica nativa de desplazamiento suave. Leer más sobre el comportamiento de desplazamiento
fuente
Hice algo como esto. No tengo idea de si está funcionando en IE8. Probado en 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(); }); }
Descripción
pointer
—Get element y chceck si tiene el atributo "href" en caso afirmativo, elimine "#"elem
: Variable de puntero sin "#"elemOffset
: Desplazamiento del elemento "desplazarse hasta" desde la parte superior de la páginafuente
Puedes usar
document.querySelector('your-element').scrollIntoView({behavior: 'smooth'});
Si desea desplazarse por la parte superior de la página, puede colocar un elemento vacío en la parte superior y desplazarse suavemente hasta ese.
fuente
Puede usar un bucle for con window.scrollTo y setTimeout para desplazarse sin problemas con JavaScript simple. Para desplazarse a un elemento con mi
scrollToSmoothly
función:scrollToSmoothly(elem.offsetTop)
(asumiendo queelem
es un elemento DOM). Puede usar esto para desplazarse suavemente a cualquier posición y en el documento.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); } }
Manifestación:
Mostrar fragmento de código
<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>
fuente
<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 = id del div que se usa para desplazarse
Nota: Para hacer que el cuerpo se desplace, déle una identificación al cuerpo.
fuente
Aquí está mi solución. Funciona en la mayoría de los navegadores.
document.getElementById("scrollHere").scrollIntoView({behavior: "smooth"});
Docs
document.getElementById("end").scrollIntoView({behavior: "smooth"});
body {margin: 0px; display: block; height: 100%; background-image: linear-gradient(red, yellow);} .start {display: block; margin: 100px 10px 1000px 0px;} .end {display: block; margin: 0px 0px 100px 0px;}
<div class="start">Start</div> <div class="end" id="end">End</div>
fuente
Con el uso del siguiente desplazamiento suave funciona bien:
fuente
Aquí está el código que funcionó para mí.
`$('a[href*="#"]') .not('[href="#"]') .not('[href="#0"]') .click(function(event) { if ( location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname ) { var target = $(this.hash); target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); if (target.length) { event.preventDefault(); $('html, body').animate({ scrollTop: target.offset().top }, 1000, function() { var $target = $(target); $target.focus(); if ($target.is(":focus")) { return false; } else { $target.attr('tabindex','-1'); $target.focus(); }; }); } } });
'
fuente