Ir directamente al contenido de esta página
Siguiendo con nuestra iniciativa de replicar efectos de animación populares de JavaScript en menos de 2Kb, creamos un ScrollTo que no depende de ninguna librería.
Habrá visto en muchos sitios web —sobre todo en los que consisten en una única página— un efecto que consiste en que al hacer clic en un vínculo interno, el documento se desplaza progresivamente hacia su destino, en lugar de simplemente «saltar» a él. Bien, pues hemos querido crear un script que duplique este comportamiento, para quien no quiera recurrir a un plugin de jQuery o MooTools.
Nuestros requisitos, los de siempre:
Antes de nada, y para los impacientes, un ejemplo funcional. Y ahora el código:
var SC = {
mov : [1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1],
url : (document.location.href.split('#'))[0],
$ : function(id){var elem = document.getElementById(id);return elem;},
ev : function(x,y,z){(document.addEventListener) ? x.addEventListener(y,z,false) : x.attachEvent('on'+y,z);},
pD : function(x){(x.preventDefault) ? x.preventDefault() : x.returnValue = false;},
sc : function(e){
SC.pD(e);
e.target ? e = e.target : e = e.srcElement;
e.toString().match('#') ? e = e : e = e.parentNode;
var o = 0,ID = (e.toString().split('#'))[1],y = SC.$(ID),x = 0,dir = 0,dis = 0,inc = 0;
window.pageYOffset ? o = window.pageYOffset : o = document.documentElement.scrollTop;
while(y){x += y.offsetTop;y = y.offsetParent;}
(x>o) ? dir = 1 : dir = -1;
dis = Math.abs(x-o);
for(var i=1;i<SC.mov.length;i++){
inc = Math.round((dir*(dis*(SC.mov[i]/100))));
o += inc;
window.scrollTo(0,o);
}
window.scrollTo(0,x);
document.location.href = SC.url+'#'+ID;
},
inicio : function(){
var vs = document.getElementsByTagName('a');
for(var i=0;i<vs.length;i++){
if(vs[i].href.match(SC.url+'#')){
SC.ev(vs[i],'click',SC.sc);
}
}
}
}
Vamos a explicar someramente algunos de los puntos del código:
$, ev y pD son funciones de apoyo, la primera simplifica la sintaxis de getElementById, y las otras dos dan cuenta de las diferencias entre Explorer y otros navegadores en la asignación de escuchas de eventos y la prevención de comportamientos por defecto, respectivamente.e.target ? e = e.target : e = e.srcElement; identifica el vínculo activado. srcElement es la propiedad de Explorer.e.toString().match('#') ? e = e : e = e.parentNode; capturamos el vínculo que se ha activado, y del que sacaremos el identificador del destino. Añadimos el e = e.parentNode, porque puede ser que el vínculo tenga dentro otro elemento —por ejemplo una imagen—, que es el que devolvería la línea anterior.window.pageYOffset ? o = window.pageYOffset : o = document.documentElement.scrollTop; nos indica la posición actual del scroll del documento, que almacenamos en o y que tomamos como el punto en el que comenzará la animación. document.documentElement.scrollTop es el código para Explorer.while(y){x += y.offsetTop;y = y.offsetParent;} calcula la distancia en píxeles desde el inicio del documento hasta el elemento de destino, almacenado en y.(x>o) ? dir = 1 : dir = -1; simplemente nos indica si el desplazamiento será ascendente o descendente.dis = Math.abs(x-o); almacena la distancia entre ambos puntos. for(var i=1;i<SC.mov.length… es el bucle que crea el movimiento. Cada vuelta calcula la cantidad de píxeles que se debe mover el scroll según el patrón de mov.window.scrollTo(0,x); asignamos explicitamente la nueva posición del documento, para corregir un posible desfase en píxeles debido al redondeo de las distancias en aquel.document.location.href = SC.url+'#'+ID; actualizamos el URL de la página.inicio simplemente revisa el árbol del documento en busca de los vínculos a los que asignar la animación.Ahora, ¿qué es exactamente mov? Es una variable que describe de forma genérica el patrón del movimiento de la animación: establece tanto el número de «fotogramas» en los que se realizará el desplazamiento, como la relación que existe entre ellos. Por ejemplo, mov : [10,10,10,10,10,10,10,10,10,10] daría lugar a una animación de cinco «saltos» de la misma distancia cada uno, con lo que su movimiento sería uniforme. En el valor que le hemos asignado por defecto, la animación consta de 19 fotogramas, y es más lenta al principio y al final para darle cierto efecto de aceleración-frenado que crea un movimiento más natural. Un patrón como [10,9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1] daría un moviento consistente sólo en la parte de frenado, y en orden inverso sólo de aceleración —nótese que la suma final siempre tiene que ser 100, puesto que definimos porcentajes de la distancia total del desplazamiento—. Y ya experimentando, [10,8,6,4,2,4,6,8,10,8,6,4,2,4,6,8,4] crearía un movimiento «ondulante». Importante: cuantos más fotogramas se incluyan, más fluido será el movimiento, aunque también se consumirán más recursos del motor de JavaScript del cliente, por lo que hay que hacerlo con moderación.
El script pesa 1,17Kb, y 994 bytes minimizado.
Y, como siempre, el script se entrega «tal cual»…
Somos un pequeño estudio fundado en 2007 por tres amigos y que actualmente cuenta con un nutrido grupo de colaboradores, todos ellos profesionales con entre ocho y once años de experiencia en diversos aspectos del desarrollo y la programación web.
Además, Digital Icon, S.L. (N.I.F.: B84622927) es una empresa inscrita en el Registro Mercantil de Madrid, Tomo 22 436, Libro 0, Folio 20, Sección 8, Hoja M-400861, Inscripción 1, conforme a los artículos 18 del Código de Comercio y 6 del Reglamento del Registro Mercantil.
Si quiere conocer un poco mejor cómo trabajamos, puede descargar una copia del contrato que firmamos con nuestros clientes o seguirnos en Google+:
Cliente: La Fábrica
División: MovilizaWeb
Nuestro trabajo: PHP, HTML5, CSS
Cliente: Ana del Val
División: EidoWeb
Nuestro trabajo: PHP, XHTML, CSS, JavaScript
Cliente: Guiomar González
División: EidoWeb
Nuestro trabajo: PHP, HTML5, CSS, jQuery
© Digital Icon, S.L., 2007 – 2012
Comentarios
¡Muy buen script!
Ahora, ¿hay alguna posibilidad de incrementar o reducir la velocidad del scroll?
Indirectamente sí: si se reduce el número de «fotogramas» de mov, como resultado se aumenta la velocidad, aunque posiblemente el efecto no sea tan fluido.
¡Intenté y nada, sigue siendo muy rápida! Si el sitio no es muy alto, no te das cuenta de que hace scrolldown.
¿Alguna otra solución?
¡¡¡Gracias!!!
Estamos programando una nueva versión en la que se pueda controlar este parámetro. En cuanto la tengamos lista subiremos una nueva entrada explicándola.
@Federico: Ya hemos publicado una versión en la que se puede controlar la velocidad.
En primer lugar enhorabuena, por el artículo y el sitio en general.
Me gustaría saber si para realizar esta función en scroll horizontal es necesarios solamente cambiar los ejes x por el y.
Muchas gracias de antemano.
Atentamente,
Julio Aliaga
Para el desplazamiento, sí, bastaría con invertir los parámetros de
window.scrollTo(0,x)a(x,0). No obstante, antes habría que emplearpageXOffset/documentElement.scrollLeftpara saber en qué punto del documento se inicia el movimiento, yoffsetLeftpara el punto de destino.¿Algún comentario?