Colores intermedios RGB

Si alguien nos pregunta ¿cuál es el color intermedio entre el blanco y el negro?, no tenemos ninguna duda y respondemos gris (y luego pensamos... ¡esta pregunta fue fácil!). Pero entre otros colores, muchas veces tenemos que pensárlo más detenidamente.

¿RGB?

Y si queremos los colores para alguna aplicación informática, tenemos que concentrarnos en el concepto RGB que proviene de las iniciales de los tres colores básicos que se necesitan: rojo, verde y azul (en inglés: Red Green Blue)

Ahora los colores dejan de serlo para convertirse en unos números que se corresponden con la cantidad o porcentaje de cada componente. En resúmen, contestando más técnicamente la pregunta inicial, el negro es ausencia de los tres componentes (rojo, verde y azul)... el blanco es la máxima cantidad de ellos... y el gris es la mitad de cada uno.

Para mostrar colores en las páginas web hay que usar su descripción en inglés, siempre que esté definido; por ejemplo existe el negro (black), el blanco (white), el gris (gray)..., pero para otras tonalidades podría no existir una descripción, así que tenemos que pensar en un sistema que indique la cantidad de cada componente del color que queremos.

Uno de esos sistemas es una especie de función "rgb()" que recibe 3 parámetros que pueden ser números entre 0 y 255, donde el blanco sería rgb(255,255,255); también pueden usarse porcentajes: rgb(100%,100%,100%). Otra forma de representación consiste en una cadena de texto empezada por el carácter almohadilla (#) seguido de los valores hexadecimales de cada componente: #FFFFFF.

Hexadecimal: conceptos básicos

En el sistema hexadecimal cada dígito puede valer entre 0 y 15 (0..F), y para los colores necesitamos un rango entre 0 y 255 (00..FF). Seguidamente mostraremos la forma de convertir valores numéricos decimales/hexadecimales ayudándonos del lenguaje javascript.

// conversión de un número entre 0 y 255 a su valor hexadecimal. 
// Por ejemplo valorHex(255) = "FF"
function valorHex(n)    { 
    return "0123456789ABCDEF".charAt(parseInt(n / 16))
	+ "0123456789ABCDEF".charAt(parseInt(n % 16)); 
} 

// conversión de un número hexadecimal "00" y "FF" 
// a su valor numérico decimal (entero positivo: 0..255).
// Por ejemplo valorDecimal("FF") = 255
function valorDecimal(s) {
  return ("0123456789ABCDEF".indexOf(s.charAt(0)) * 16) 
	+ "0123456789ABCDEF".indexOf(s.charAt(1));
}

Con la ayuda de estos conversores que acabamos de definir podemos manipular mejor los colores de nuestra página. Propongo a continuación la declaración de un objeto "Color", donde la definición se realiza introduciendo como parámetro sus tres componentes en forma numérica, o si se prefiere como una cadena de texto.

// Objeto Color: a partir de sus 3 componentes
// Entero positivo: 0..255
function Color(Rojo, Verde, Azul)	{
	this.Rojo = Rojo;
	this.Verde = Verde;
	this.Azul = Azul;
	this.toString = function()	{
		return "#" + valorHex(this.Rojo) + valorHex(this.Verde) + valorHex(this.Azul);
	}
	this.toArray = function()	{
		return new Array(this.Rojo, this.Verde, this.Azul);
	}
	this.fromString = function(s)	{
		return new Color(valorDecimal(s.substr(1, 2)), 
			valorDecimal(s.substr(3, 2)),
			valorDecimal(s.substr(5, 2)));
	}
}

Notese la definición de los métodos toString(), toArray() y fromString(s)... en realidad "toString()" es una re-definicaión ya que los objetos javascript implementan de forma inherente este método cuya finalidad es representarlos; toArray() devuele los componentes como un array. También puede formarse una cadena de este tipo:

"rgb(" + negro.toArray() + ")"

... fromString() es un método que permite la construcción del color a partir de otro color representado por una cadena. He creído conveniente usar una representación que nos permita su uso directo.

O sea que con este código son válidas las siguientes definiciones:

var negro = new Color(0, 0, 0);
var blanco = new Color().fromString("#FFFFFF");
// Para obtener el color como una cadena 
// bastaría con poner el nombre de la variable:
alert(negro);
// Y si quisieramos obtener el color como un array de
// sus tres componentes habría que añadirle la coletilla
// toArray() al nombre de la variable:
alert(negro.toArray());
// Por último podemos obtener el valor de cada componente 
// consultando el atributo correspondiente
alert(negro.Rojo);

Los valores intermedios

Teniendo las declaraciones necesarias para manipular colores nos centraremos en la obtención de los valores intermedios. Para ello debemos obtener un número que he denominado ratio, que sumándolo a cada componente nos permite obtener el siguiente. De más está decir que esos valores también pueden ser negativos.

function coloresIntermedios(inicial, final, pasos)	{
	var resultado = new Array(pasos--);
	resultado[0] = inicial;
	resultado[pasos] = final;
	ratio = new Color(parseInt((final.Rojo - inicial.Rojo) / pasos),
		parseInt((final.Verde - inicial.Verde) / pasos),
		parseInt((final.Azul - inicial.Azul) / pasos));
	for (var i = 1; i < pasos; i ++)
		resultado[i] = new Color(inicial.Rojo + (ratio.Rojo * i), 
			inicial.Verde + (ratio.Verde * i),
			inicial.Azul + (ratio.Azul * i));
	return resultado;
}

Una sencilla aplicación

Si quisieramos obtener esos datos intermedios introduciendo por teclado los colores inicial y final, además del número de valores intermedios, nos bastaría un pequeño formulario con 3 elementos para la entrada de datos, un botón para poner en funcionamiento nuestro script, y un elemento que muestre esos datos.

<form name="intermedios" action="" method="get" >
color inicial:<input type="text" name="ini" value="#000000" />
color final:<input type="text" name="fin" value="#FFFFFF" />
pasos:<input type="text" name="pasos" value="5" />
<textarea name="resultado" style="width: 70%; height: 150px;"></textarea>
<br/>
<button 
	onclick="resultado.value = coloresIntermedios(new Color().fromString(ini.value),
		new Color().fromString(fin.value), pasos.value)" >
obtener intermedios
</button>
</form>

Algunos usos

Se me ocurren dos posibles usos para este sistema: fondos degradados en botones, capas y páginas; y efecto fade en textos. Se puede apreciar estas dos funcionalidades en la siguiente página: Gradientes (php + librerías GD)

Otros enlaces relacionados

Para quien desee más información: