palettes - Gradiente de color Javascript
w3schools color scheme (9)
Al usar javascript con o sin Jquery, necesito crear un degradado de colores basado en un color de inicio y final. ¿Es esto posible hacerlo programáticamente?
El color final solo tendrá un tono más oscuro del color de inicio y es para una lista desordenada que no tengo control sobre la cantidad de elementos li. Estoy buscando una solución que me permita elegir un color de inicio y final, convertir el valor hexadecimal en RGB para que pueda ser manipulado en código. Los valores RGB iniciales se incrementan en un valor de paso calculado en función del número de elementos.
entonces, si la lista tiene 8 elementos, entonces necesita incrementar los valores separados de Rojo Verde Azul en 8 pasos para lograr el color final. ¿Existe una mejor manera de hacerlo y, de ser así, dónde puedo encontrar algún código de muestra?
La biblioteca xolor tiene una función de gradiente. Esto creará una matriz con 8 colores en un degradado de un color inicial a uno final:
var gradientColors = []
var startColor = "rgb(100,200,50)", endColor = "green"
var start = xolor(startColor)
for(var n=0; n<8; n++) {
gradientColors.push(start.gradient(endColor, n/8))
}
Ver más en github: https://github.com/fresheneesz/xolor
Necesitaba crear una gran variedad de opciones de color para un conjunto desconocido de elementos dinámicos, pero necesitaba que cada elemento se incrementara a través de un color inicial y un color final. Este tipo de enfoque sigue el enfoque de "porcentaje de fundido", excepto que tuve dificultades para seguir esa lógica. Así es como me acerqué usando entradas de dos valores de color rgb y calculando el número de elementos en la página.
Aquí hay un enlace a un codepen que demuestra el concepto.
A continuación se muestra un fragmento de código del problema.
<style>
#test {
width:200px;
height:100px;
border:solid 1px #000;
}
.test {
width:49%;
height:100px;
border:solid 1px #000;
display: inline-block;
}
</style>
</head>
<body>
<div id="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<script>
var GColor = function(r,g,b) {
r = (typeof r === ''undefined'')?0:r;
g = (typeof g === ''undefined'')?0:g;
b = (typeof b === ''undefined'')?0:b;
return {r:r, g:g, b:b};
};
// increases each channel by the difference of the two
// divided by 255 (the number of colors stored in the range array)
// but only stores a whole number
// This should respect any rgb combinations
// for start and end colors
var createColorRange = function(c1) {
var colorList = [], tmpColor, rr = 0, gg = 0, bb = 0;
for (var i=0; i<255; i++) {
tmpColor = new GColor();
if (rExp >= 0) {
tmpColor.r = Math.floor(c1.r - rr);
rr += rAdditive;
} else {
tmpColor.r = Math.floor(c1.r + rr);
rr += rAdditive;
}
if (gExp >= 0) {
tmpColor.g = Math.floor(c1.g - gg);
gg += gAdditive;
} else {
tmpColor.g = Math.floor(c1.g + gg);
gg += gAdditive;
}
if (bExp >= 0) {
tmpColor.b = Math.floor(c1.b - bb);
bb += bAdditive;
} else {
tmpColor.b = Math.floor(c1.b + bb);
bb += bAdditive;
}
console.log(tmpColor);
colorList.push(tmpColor);
}
return colorList;
};
/* ==================
Testing Code Below
================== */
var firstColor = new GColor(255, 24, 0);
var secondColor = new GColor(255, 182, 0);
// Determine the difference
var rExp = firstColor.r - secondColor.r;
// Divide that difference by length of the array
// you would like to create (255 in this case)
var rAdditive = Math.abs(rExp)/255;
var gExp = firstColor.g - secondColor.g;
var gAdditive = Math.abs(gExp)/255;
var bExp = firstColor.b - secondColor.b;
var bAdditive = Math.abs(bExp)/255;
var range = createColorRange(firstColor, secondColor);
console.log(range);
var pointer = 0;
// This gently cycles through
// all the colors on a single element
function rotateColors() {
var currentColor = range[pointer];
document.getElementById("test").style.backgroundColor = "rgb("+currentColor.r+","+currentColor.g+","+currentColor.b+")";
pointer++;
if (pointer < range.length) window.setTimeout(rotateColors, 5);
}
rotateColors();
// say I have 5 elements
// so I need 5 colors
// I already have my first and last colors
// but I need to locate the colors between
// my start color and my end color
// inside of this range
// so I divide the range''s length by the
// number of colors I need
// and I store the index values of the middle values
// those index numbers will then act as my keys to retrieve those values
// and apply them to my element
var myColors = {};
var objects = document.querySelectorAll(''.test'');
myColors.num = objects.length;
var determineColors = function(numOfColors, colorArray) {
var colors = numOfColors;
var cRange = colorArray;
var distance = Math.floor(cRange.length/colors);
var object = document.querySelectorAll(''.test'');
var j = 0;
for (var i = 0; i < 255; i += distance) {
if ( (i === (distance*colors)) ) {
object[j].style.backgroundColor = "rgb(" + range[255].r + ", " + range[255].g + ", " + range[255].b + ")";
j = 0;
// console.log(range[i]);
} else {
// Apply to color to the element
object[j].style.backgroundColor = "rgb(" + range[i].r + ", " + range[i].g + ", " + range[i].b + ")";
// Have each element bleed into the next with a gradient
// object[j].style.background = "linear-gradient( 90deg, rgb(" + range[i].r + ", " + range[i].g + ", " + range[i].b + "), rgb(" + range[i+distance].r + ", " + range[i+distance].g + ", " + range[i+distance].b + "))";
j++;
}
}
};
setTimeout( determineColors(myColors.num, range), 2000);
</script>
</body>
No tan poderoso, pero en la mayoría de los casos funciona y no tiene que incluir ninguna otra biblioteca, excepto jQuery para el siguiente código:
HTML:
<div id="colors"></div>
JavaScript:
function rainbow(value, s, l, max, min, start, end) {
value = ((value - min) * (start - end) / max)+end;
return ''hsl('' + value + '',''+s+''%,''+l+''%)'';
}
function createRainbowDiv(start,end){
var gradient = $("<div>").css({display:"flex", "flex-direction":"row",height:"100%"});
for (var i = start; ((i <= end) && (i >= start)) || ((i >= end) && (i <= start));
i += (end-start) / Math.abs(end-start)){
gradient.append($("<div>").css({float:"left","background-color":rainbow(i, 100,50, Math.max(start,end), Math.min(start,end), start,end),flex:1}));
}
return gradient;
}
$("#colors").append(createRainbowDiv(0,150));
$("#colors").css("width","100%").css("height","10px");
Esto debería hacer un div que contenga un arcoiris. Ver http://jsfiddle.net/rootandy/54rV7/
Puede recuperar la lista de elementos. No estoy familiarizado con jQuery, pero prototypejs tiene Element.childElements () que devolverá una matriz. Una vez que sepa la longitud de la matriz, puede determinar cuánto cambiar los componentes de píxeles para cada paso. Algunos de los siguientes códigos no los he probado en la forma en que los estoy presentando, pero espero que les dé una idea.
function hex (c) {
var s = "0123456789abcdef";
var i = parseInt (c);
if (i == 0 || isNaN (c))
return "00";
i = Math.round (Math.min (Math.max (0, i), 255));
return s.charAt ((i - i % 16) / 16) + s.charAt (i % 16);
}
/* Convert an RGB triplet to a hex string */
function convertToHex (rgb) {
return hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
/* Remove ''#'' in color hex string */
function trim (s) { return (s.charAt(0) == ''#'') ? s.substring(1, 7) : s }
/* Convert a hex string to an RGB triplet */
function convertToRGB (hex) {
var color[];
color[0] = parseInt ((trim(hex)).substring (0, 2), 16);
color[1] = parseInt ((trim(hex)).substring (2, 4), 16);
color[2] = parseInt ((trim(hex)).substring (4, 6), 16);
}
/* The start of your code. */
var start = convertToRGB (''#000000''); /* The beginning of your gradient */
var end = convertToRGB (''#ffffff''); /* The end of your gradient */
var arr = $(''.gradientList'').childElements();
var len = arr.length(); /* The number of colors to compute */
var alpha = 0.5; /* Alpha blending amount */
for (i = 0; i < len; i++) {
var c = [];
c[0] = start[0] * alpha + (1 - alpha) * end[0];
c[1] = start[1] * alpha + (1 - alpha) * end[1];
c[2] = start[2] * alpha + (1 - alpha) * end[2];
/* Set the background color of this element */
arr[i].setStyle ({ ''background-color'': convertToHex (c) });
}
Si, absolutamente.
Hago esto en Java, debería ser bastante simple de hacer en JavaScript también.
Primero, deberá dividir los colores en componentes RGB.
Luego calcule las diferencias entre el inicio y el final de los componentes.
Finalmente, calcule la diferencia porcentual y multiplique por el color inicial de cada componente, luego agréguelo al color inicial.
Suponiendo que pueda obtener los valores RGB, esto debería hacerlo:
var diffRed = endColor.red - startColor.red;
var diffGreen = endColor.green - startColor.green;
var diffBlue = endColor.blue - startColor.blue;
diffRed = (diffRed * percentFade) + startColor.red;
diffGreen = (diffGreen * percentFade) + startColor.green;
diffBlue = (diffBlue * percentFade) + startColor.blue;
El "percentFade" es un decimal flotante, que indica qué tan lejos se desvanece en el "endColor". 1 sería un fundido completo (creando así el color final). 0 no sería un fundido (el color inicial).
Uso esta función en función de la respuesta de @desau:
getGradientColor = function(start_color, end_color, percent) {
// strip the leading # if it''s there
start_color = start_color.replace(/^/s*#|/s*$/g, '''');
end_color = end_color.replace(/^/s*#|/s*$/g, '''');
// convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
if(start_color.length == 3){
start_color = start_color.replace(/(.)/g, ''$1$1'');
}
if(end_color.length == 3){
end_color = end_color.replace(/(.)/g, ''$1$1'');
}
// get colors
var start_red = parseInt(start_color.substr(0, 2), 16),
start_green = parseInt(start_color.substr(2, 2), 16),
start_blue = parseInt(start_color.substr(4, 2), 16);
var end_red = parseInt(end_color.substr(0, 2), 16),
end_green = parseInt(end_color.substr(2, 2), 16),
end_blue = parseInt(end_color.substr(4, 2), 16);
// calculate new color
var diff_red = end_red - start_red;
var diff_green = end_green - start_green;
var diff_blue = end_blue - start_blue;
diff_red = ( (diff_red * percent) + start_red ).toString(16).split(''.'')[0];
diff_green = ( (diff_green * percent) + start_green ).toString(16).split(''.'')[0];
diff_blue = ( (diff_blue * percent) + start_blue ).toString(16).split(''.'')[0];
// ensure 2 digits by color
if( diff_red.length == 1 ) diff_red = ''0'' + diff_red
if( diff_green.length == 1 ) diff_green = ''0'' + diff_green
if( diff_blue.length == 1 ) diff_blue = ''0'' + diff_blue
return ''#'' + diff_red + diff_green + diff_blue;
};
Ejemplo:
getGradientColor(''#FF0000'', ''#00FF00'', 0.4);
=> "#996600"
RainbowVis-JS una biblioteca JS, RainbowVis-JS para resolver este problema general. Solo tiene que establecer el número de elementos usando setNumberRange
y establecer el color de inicio y final con setSpectrum
. Luego obtienes el código de color hexadecimal con colourAt
.
var numberOfItems = 8;
var rainbow = new Rainbow();
rainbow.setNumberRange(1, numberOfItems);
rainbow.setSpectrum(''red'', ''black'');
var s = '''';
for (var i = 1; i <= numberOfItems; i++) {
var hexColour = rainbow.colourAt(i);
s += ''#'' + hexColour + '', '';
}
document.write(s);
// gives:
// #ff0000, #db0000, #b60000, #920000, #6d0000, #490000, #240000, #000000,
Le invitamos a mirar el código fuente de la biblioteca. :)
¡Función correcta para generar una matriz de colores!
function hex (c) {
var s = "0123456789abcdef";
var i = parseInt (c);
if (i == 0 || isNaN (c))
return "00";
i = Math.round (Math.min (Math.max (0, i), 255));
return s.charAt ((i - i % 16) / 16) + s.charAt (i % 16);
}
/* Convert an RGB triplet to a hex string */
function convertToHex (rgb) {
return hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
/* Remove ''#'' in color hex string */
function trim (s) { return (s.charAt(0) == ''#'') ? s.substring(1, 7) : s }
/* Convert a hex string to an RGB triplet */
function convertToRGB (hex) {
var color = [];
color[0] = parseInt ((trim(hex)).substring (0, 2), 16);
color[1] = parseInt ((trim(hex)).substring (2, 4), 16);
color[2] = parseInt ((trim(hex)).substring (4, 6), 16);
return color;
}
function generateColor(colorStart,colorEnd,colorCount){
// The beginning of your gradient
var start = convertToRGB (colorStart);
// The end of your gradient
var end = convertToRGB (colorEnd);
// The number of colors to compute
var len = colorCount;
//Alpha blending amount
var alpha = 0.0;
var saida = [];
for (i = 0; i < len; i++) {
var c = [];
alpha += (1.0/len);
c[0] = start[0] * alpha + (1 - alpha) * end[0];
c[1] = start[1] * alpha + (1 - alpha) * end[1];
c[2] = start[2] * alpha + (1 - alpha) * end[2];
saida.push(convertToHex (c));
}
return saida;
}
// Exemplo de como usar
var tmp = generateColor(''#000000'',''#ff0ff0'',10);
for (cor in tmp) {
$(''#result_show'').append("<div style=''padding:8px;color:#FFF;background-color:#"+tmp[cor]+"''>COLOR "+cor+"° - #"+tmp[cor]+"</div>")
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result_show"></div>
La respuesta de desau es genial. Aquí está en javascript:
function hexToRgb(hex) {
var result = /^#?([a-f/d]{2})([a-f/d]{2})([a-f/d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
function map(value, fromSource, toSource, fromTarget, toTarget) {
return (value - fromSource) / (toSource - fromSource) * (toTarget - fromTarget) + fromTarget;
}
function getColour(startColour, endColour, min, max, value) {
var startRGB = hexToRgb(startColour);
var endRGB = hexToRgb(endColour);
var percentFade = map(value, min, max, 0, 1);
var diffRed = endRGB.r - startRGB.r;
var diffGreen = endRGB.g - startRGB.g;
var diffBlue = endRGB.b - startRGB.b;
diffRed = (diffRed * percentFade) + startRGB.r;
diffGreen = (diffGreen * percentFade) + startRGB.g;
diffBlue = (diffBlue * percentFade) + startRGB.b;
var result = "rgb(" + Math.round(diffRed) + ", " + Math.round(diffGreen) + ", " + Math.round(diffBlue) + ")";
return result;
}
function changeBackgroundColour() {
var count = 0;
window.setInterval(function() {
count = (count + 1) % 200;
var newColour = getColour("#00FF00", "#FF0000", 0, 200, count);
document.body.style.backgroundColor = newColour;
}, 20);
}
changeBackgroundColour();