Con unas pocas líneas de código podemos conseguir un efecto de fundido que permitirá que nuestra página sea más vistosa. Nos ayudaremos de información que tenemos en el artículo Colores intermedios RGB.
Basándonos en el artículo mencionado, hemos preparado el siguiente formulario con el que obtendremos una variable del tipo array con los n colores intermedios de dos dados:
Donde el primer color se llama "c1", el segundo "c2" y el número de pasos "p"; usando un método llamado coloresIntermedios similar al del artículo mencionado anteriormente, tan solo hay que definir el comportamiento del botón como sigue:
<button type="button" onclick="resultado.value = ' var colores = ["' + coloresIntermedios(c1.value, c2.value, p.value).join('", "') + '"];'" > obtener resultados </button>
A partir de ahora tenemos que copiar de nuestro formulario el código generado y pegarlo en la sección script de nuestra página para usarlo en nuestro efecto.
Ya tenemos algo muy importante: los colores de inicio y fin del efecto y el número de pasos intermedios (la longitud del array resultante), ahora necesitamos referenciar el elemento al que vamos a aplicar el efecto y una variable que indique el retardo entre un color y el siguiente.
Definiremos los métodos que vamos a utilizar con los nombres cambiaColor y recuperaColor:
function cambiaColor(colores, id, ms) { ... } function recuperaColor(colores, id, ms) { ... }
Se nos presenta un problema de fácil resolución, pero muy poco documentado ya que los colores están en un arreglo y tenemos que hacer llamadas recursivas invocándolos.
No es problemático el uso de métodos recursivos y variables, pero en este caso tenemos que hacer la recursión con retardos; concretamente usaremos el método setTimeout(), al que tenemos que pasar como primer parámetro un texto que represente lo que queremos hacer y como segundo parámetro un número entero que se corresponde con el retardo en milisegundos que aplicaremos.
Los ejemplos más básicos sobre el uso de este método es una llamada simple a un método:
setTimeout("miMetodo()", 1000);
O incluír algunos datos simples dentro de esos paréntesis:
miVar = "¡Hola Mundo!";
setTimeout("alert('" + miVar + "')", 1000);
Pero con datos más complejos hay que usar otros truquillos... Con una estructura array debemos convertirlo a un texto, y para ello tenemos que usar el método join que aplicado a un array lo convierte en una cadena de sus elementos separados por la cadena de caracteres que se pasa como parámetro.
Sin olvidarnos que esos elementos deben mostrarse entre corchetes, vamos a mostrar el primer elemento de un array de colores (como el que se genera con el formulario que hemos visto) aplicando un retardo de 1 segundo:
setTimeout("alert(['" + colores.join("','") + "][0]", 1000);
Aunque el expuesto es un método válido, convertir un array muy grande puede generar un texto demasiado extenso, así que usaremos un segundo truco mucho más sencillo que consiste en pasar la variable por su nombre, y para recoger el valor usamos ese nombre (simple texto) como un atributo dependiente del objeto window.
var fondos = window[colores]; // fondos recibe el array de colores.
Ya sabiendo resolver el problema de la recursión, vamos a plantear como generamos el texto que nos servirá para ella, suponiendo que la función se llame transitarColor, la línea quedará así:
var recurrir = "transitarColor('" + colores + "', '" + id + "', " + ms + ")"; setTimeout(recurrir, ms);
Tan solo nos queda saber el índice del color en cada momento, y un indicador que nos sirva para saber si ese índice crece o decrece. Podríamos pasar también esos valores en la recursión, pero en este caso vamos a guardar esos datos en el mismo elemento que usamos para el efecto, asignando o leyendo esos valores según los casos con los métodos setAttribute() y getAttribute().
Mostramos ahora el contenido de los 2 métodos que usaremos para inicializar las variables en los elementos, y llamar al método recursivo:
function cambiaColor(colores, id, ms) { var fondos = window[colores]; var elemento = document.getElementById(id); elemento.setAttribute("incremento", "-1"); elemento.setAttribute("valor", (fondos.length - 2).toString()); transitarColor(colores, id, ms); } function recuperaColor(colores, id, ms) { var elemento = document.getElementById(id); elemento.setAttribute("incremento", "1"); if (parseInt(elemento.getAttribute("valor")) < 0) elemento.setAttribute("valor", "1"); transitarColor(colores, id, ms); }
Nótese la obtención del array de colores a partir del literal de la variable, cómo se obtiene un elemento a partir de su id, y cómo se asignan valores a atributos nuevos.
Solo queda definir el método transitarColor() que se encargará de actualizar el color, y continuar con la transición.
function transitarColor(colores, id, ms) { var fondos = window[colores]; var elemento = document.getElementById(id); var incre = parseInt(elemento.getAttribute("incremento")); var valorActual = parseInt(elemento.getAttribute("valor")); var nuevoValor = valorActual + incre; elemento.setAttribute("valor", nuevoValor); if (nuevoValor >= 0 && nuevoValor < (fondos.length)) { elemento.style.backgroundColor = fondos[nuevoValor]; elemento.style.color = fondos[(fondos.length) - nuevoValor - 1]; var recurrir = "transitarColor('" + colores + "', '" + id + "', " + ms + ")"; setTimeout(recurrir, ms); } }
Este párrafo invertirá sus colores cuando se pose el ratón sobre él, y se restaurarán al quitarlo. Será una transición con 30 colores intermedios entre el negro (#000000) y el blanco (#FFFFFF) con un retardo de 30 milisegundos.
La definición de la etiqueta ha sido la siguiente:
<p id="ejemplo" onmouseover="cambiaColor('colores', this.id, 30)" onmouseout="recuperaColor('colores', this.id, 30)" >
Estas pocas líneas de código permiten algo más de juego modificando la cantidad de colores intermedios y la velocidad en la transición, pero con pocos cambios también puede seleccionarse un elemento: fondo y/o texto. O crear una especie de banner de texto (véase el titular de esta sección). Otro claro ejemplo en donde la imaginación pone los límites...
Aparte del artículo citado al comienzo, son interesantes las siguientes referencias: