Blog para los que realmente programan páginas web

domingo, 22 de marzo de 2015

En esta segunda entrega crearé un banner rotatorio usando las opciones de animación que brinca CSS3.

Introducción a los prefijos en CSS3:

Aunque el consorcio del estándar "WWW" (llamado W3C) recomienda que se use la propiedad "animation" y la regla @keyframes cada "fabricante" ha puesto su prefijo en las propiedades y las reglas.

Hace muchos años, cuando comenzó el cambio, propuestas, borradores (drafts), etc los mayores "fabricantes" de navegadores tenían sus propios prefijos: Opera tenía su prefijo -o-, Internet Explorer usaba -ms- y Safari/chrome usan -webkit.

Después de un tiempo Opera "acogió" una gran cantidad de extensiones de extensiones de -webkit- como suyas, por lo que en la actualidad con un único prefijo (-webkit-) se consigue compatibilidad con Opera, Safari y Chrome, mientras que Internet Explorer sigue necesitando la suya propia (-ms-) aunque a partir de la versión 10 del navegador ya no son necesarios la gran mayoría de prefijos (aunque deben mantenerse por compatibilidad con versiones anteriores).

En definitiva, por ahora parece que el único que se ha tirado a la piscina ha sido el navegador de Microsoft, me entristece que no haya sido un movimiento común de todos los "grandes".

Versión sin JavaScript

Tras esta breve introducción vayamos al grano. En el código HTML introduciremos un elemento "div" al que aplicaremos como imagen de fondo aquella imagen que queremos animar.

Código HTML:

<div class="contenedor"></div>

Hoja de estilos CSS:

.contenedor {
    width: 100%;
    height: 200px;
    margin: 0px;
    background: white url(http://redstar.linaresdigital.com/imagenesblog/programacion-web/patron-repetido.png) 0px 0px;
    -webkit-animation: animacion 10s linear infinite;
    -ms-animation: animacion 10s linear infinite;
    animation: animacion 10s linear infinite;
}

@-webkit-keyframes animacion {
    0% { background-position: 346px 0px; }
    100% { background-position: 0px 0px; }
}
@-ms-keyframes animacion {
    0% { background-position: 346px 0px; }
    100% { background-position: 0px 0px; }
}
@keyframes animacion {
    0% { background-position: 346px 0px; }
    100% { background-position: 0px 0px; }
}

En este caso la hoja de estilos se complica un poco, pero está dividida claramente en dos partes:

  • Primera parte: definición del estilo de la capa. En la definición fijamos el ancho al 100% de la página y el alto al mismo que el fondo (aunque al ser un fondo que permite repetición podría ser mayor). El "truco" lo hace la propiedad "animation" que hace referencia a la regla que definiremos en la segunda parte, llamada "animacion", y a la duración de la animación, 10 segundos, tipo de avance temporal, lineal, y número de iteraciones, infinitas.
  • Segunda parte: definición de la animación. La regla "animacion" define que al comienzo de la misma (al 0% de ella) la posición del fondo estará en el extremo derecho, y al 100% a la izquierda. Eso hará que el fondo se anime de derecha a izquierda, completando el movimiento en 10 segundos tal y como definimos en la propiedad "animation".

Puedes probar este código online aquí: http://jsfiddle.net/OscarGarcia/uya5jg7k/

Versión con JavaScript

Para hacer este efecto "a la vieja usanza" deberemos hacer uso del evento "load" de window para comenzar la animación y de la propiedad "style.backgroundPosition" de la capa para modificar gradualmente la posición de fondo.

Código HTML:

<div class="contenedor"></div>

Hoja de estilos CSS:

.contenedor {
    width: 100%;
    height: 200px;
    margin: 0px;
    background: white url(http://redstar.linaresdigital.com/imagenesblog/programacion-web/patron-repetido.png) 0px 0px;
}

Código JavaScript:

/* 10 segundos por cada transición */
var tiempo = 10000;
/* Ancho de la imagen de fondo en pixeles */
var ancho = 346; // ancho de la imagen
/* Objeto que "fondopos" tratará, para evitar usar IIFE */
var contenedor;

/* Función que genera la secuencia de animación de cada ciclo */
function generar() {
    /* Incremento de tiempo en cada movimiento de pixel. */
    var intervalo = tiempo / ancho;
    /* No es pesado buscar el elemento por cada 10 segundos */
    contenedor = document.getElementById("contenedor");
    console.log("B");
    var t;
    /* Animamos de pixel en pixel para asegurar algo de suavidad en la animación */
    for (xpos = ancho, t = 0; xpos > 0; xpos--, t += intervalo) {
        setTimeout("fondopos(" + xpos + ", 0)", t);
    }
    /* Al final de la secuencia nos volvemos a llamar para inciar la siguiente */
    setTimeout("generar()", tiempo);
}

/* Función que modifica el estilo CSS para animar la posición del fondo */
function fondopos(x, y) {
    contenedor.style.backgroundPosition = String(x) + "px " + String(y) + "px";
}

/* En cuanto cargue el documento iniciamos la animación */
window.onload = generar;

El código Javascript es auto explicativo. El único "truco" que he usado ha sido, para evitar usar IIFE, la creación de la cadena del "setTimeout" que genera la llamada a la función "fondopos" concatenando (como texto, aunque se interpretarán como números) los parámetros de la llamada.

Por ahora no quiero complicar más el código, por lo que más adelante trataremos el problema(?) de IIFE más adelante.

A modo de depuración se escribirá una "B" en la consola de javascript cada vez que se ejecute un ciclo de animación (una llamada a la función "generar").

Puedes probar este código online aquí: http://jsfiddle.net/OscarGarcia/09wb6sxg/

Conclusión

A continuación compararé, en términos de uso de CPU, ambas soluciones.

Antes de continuar he de comentar que tuve que quitar la vista preliminar del código en jsfiddle para que la página no sobrecargara la CPU del visitante del blog. Ésta subía fácilmente al 100% dependiendo de la potencia del equipo.

  • Versión CSS3:
    • Uso de CPU: 55-60%
    • Uso de memoria: 37M
  • Versión JavaScript:
    • Uso de CPU: 35-35%
    • Uso de memoria: 38M, subiendo unos 600K por minuto.

Es curioso pensar que una versión "pesada" en la que la animación está guiada por código JavaScript, y no código nativo del navegador, requiere de menos carga de CPU para ejecutarse. El principal problema de la versión de JavaScript es la creación de 346 eventos setTimeout cada 10 segundos que con mucha probabilidad son los responsables del aumento del consumo de memoria del navegador.

0 comentarios:

Publicar un comentario