问题
Alright thought I would throw this one out there for the crowd to think over.
Given a function (written in javascript) that expects two strings formated like a hex color (ex #FF0000)
return a hex color that is the average of both of the colors passed.
function averageColors(firstColor,secondColor)
{
...
return avgColor;
}
--edit--
average would be defined as
if the color passed was yellow and the second was light purple the returned color would be a medium orange
回答1:
I hate sounding like the oh-so-broken jQuery record, but there is a jQuery plugin for this already.
回答2:
Only requires a few lines of POJS if you don't want to bother with lots of unnecessary stuff:
// Expects input as 'nnnnnn' where each nn is a
// 2 character hex number for an RGB color value
// e.g. #3f33c6
// Returns the average as a hex number without leading #
var averageRGB = (function () {
// Keep helper stuff in closures
var reSegment = /[\da-z]{2}/gi;
// If speed matters, put these in for loop below
function dec2hex(v) {return v.toString(16);}
function hex2dec(v) {return parseInt(v,16);}
return function (c1, c2) {
// Split into parts
var b1 = c1.match(reSegment);
var b2 = c2.match(reSegment);
var t, c = [];
// Average each set of hex numbers going via dec
// always rounds down
for (var i=b1.length; i;) {
t = dec2hex( (hex2dec(b1[--i]) + hex2dec(b2[i])) >> 1 );
// Add leading zero if only one character
c[i] = t.length == 2? '' + t : '0' + t;
}
return c.join('');
}
}());
回答3:
Smells like homework to me, but here's my clue.
Take each hex value for R, G, and B, and average each of them. If necessary convert to Decimal to do the math.
function d2h(d) {return d.toString(16).padStart(2,'0');}
function h2d(h) {return parseInt(h,16);}
Then return a string containing the concatenated values of the three elements.
回答4:
A quick/dirty/convenient/ES6 way to blend two hex colors by a specified perecentage:
// blend two hex colors together by an amount
function blendColors(colorA, colorB, amount) {
const [rA, gA, bA] = colorA.match(/\w\w/g).map((c) => parseInt(c, 16));
const [rB, gB, bB] = colorB.match(/\w\w/g).map((c) => parseInt(c, 16));
const r = Math.round(rA + (rB - rA) * amount).toString(16).padStart(2, '0');
const g = Math.round(gA + (gB - gA) * amount).toString(16).padStart(2, '0');
const b = Math.round(bA + (bB - bA) * amount).toString(16).padStart(2, '0');
return '#' + r + g + b;
}
console.log(blendColors('#00FF66', '#443456', 0.5));
Where amount
should be 0
to 1
, with 0
being exactly colorA
, 1
being exactly colorB
, and 0.5
being the "midpoint".
回答5:
Here is my function, hope it helps.
function averageColors( colorArray ){
var red = 0, green = 0, blue = 0;
for ( var i = 0; i < colorArray.length; i++ ){
red += hexToR( "" + colorArray[ i ] + "" );
green += hexToG( "" + colorArray[ i ] + "" );
blue += hexToB( "" + colorArray[ i ] + "" );
}
//Average RGB
red = (red/colorArray.length);
green = (green/colorArray.length);
blue = (blue/colorArray.length);
console.log(red + ", " + green + ", " + blue);
return new THREE.Color( "rgb("+ red +","+ green +","+ blue +")" );
}
//get the red of RGB from a hex value
function hexToR(h) {return parseInt((cutHex( h )).substring( 0, 2 ), 16 )}
//get the green of RGB from a hex value
function hexToG(h) {return parseInt((cutHex( h )).substring( 2, 4 ), 16 )}
//get the blue of RGB from a hex value
function hexToB(h) {return parseInt((cutHex( h )).substring( 4, 6 ), 16 )}
//cut the hex into pieces
function cutHex(h) {if(h.charAt(1) == "x"){return h.substring( 2, 8 );} else {return h.substring(1,7);}}
回答6:
Very late to this party, but I was personally looking for a way to average an undefined amount of HEX values. Based on the answer @RobG, I came up with this. Granted, the more colors you add the more brown/greyish they get, but, perhaps it helps!
/**
* Averages an array of hex colors. Returns one hex value (with leading #)
*
* @param {Array} colors - An array of hex strings, e.g. ["#001122", "#001133", ...]
*/
function averageHex(colors) {
// transform all hex codes to integer arrays, e.g. [[R, G, B], [R,G,B], ...]
let numbers = colors.map(function(hex) {
// split in seperate R, G and B
let split = hex.match(/[\da-z]{2}/gi);
// transform to integer values
return split.map(function(toInt) {
return parseInt(toInt, 16);
});
});
// reduce the array by averaging all values, resulting in an average [R, G, B]
let averages = numbers.reduce(function(total, amount, index, array) {
return total.map(function(subtotal, subindex) {
// if we reached the last color, average it out and return the hex value
if (index == array.length - 1) {
let result = Math.round((subtotal + amount[subindex]) / array.length).toString(16);
// add a leading 0 if it is only one character
return result.length == 2 ? '' + result : '0' + result;
} else {
return subtotal + amount[subindex];
}
});
});
// return them as a single hex string
return "#" + averages.join('');
}
console.log(averageHex(["#FF110C", "#0000AA", "#55063d", "#06551e"]));
// expected: #571b44, see also https://www.colorhexa.com/ and enter "#FF110C+#0000AA+#55063d+#06551e"
回答7:
Here's a compact set of relevant (interdependent) functions:
Hex ⟷ RGB Color Conversion:
function hexToRgb(h){return['0x'+h[1]+h[2]|0,'0x'+h[3]+h[4]|0,'0x'+h[5]+h[6]|0]}
function rgbToHex(r,g,b){return"#"+((1<<24)+(r<<16)+(g<<8)+ b).toString(16).slice(1);}
Calculate Average of 2 Hex Colors: Requires conversion functions (above)
function avgHex(h1,h2){a=hexToRgb(h1);b=hexToRgb(h2); return rgbToHex(~~((a[0]+b[0])/2),~~((a[1]+b[1])/2),~~((a[2]+b[2])/2));}
Generate Random Hex Color:
function rndHex(){return'#'+('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6);}
Run snippet for demo:
// color functions (average/random/conversion)
function hexToRgb(h){return['0x'+h[1]+h[2]|0,'0x'+h[3]+h[4]|0,'0x'+h[5]+h[6]|0]}
function rgbToHex(r,g,b){return"#"+((1<<24)+(r<<16)+(g<<8)+ b).toString(16).slice(1);}
function rndHex(){return'#'+('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6);}
function avgHex(h1,h2){a=hexToRgb(h1);b=hexToRgb(h2);return rgbToHex(~~((a[0]+b[0])/2),~~((a[1]+b[1])/2),~~((a[2]+b[2])/2));}
//code below is just for the demo
function auto(){if(chk.checked){tmr=setInterval(rnd,1000)}else{clearTimeout(tmr)}}auto();
function rnd(go){for(h of[h1,h2]){h.value=rndHex();}avgInput();}
addEventListener('input',avgInput);
function avgInput(){ // get avg & colorize
ha.value=avgHex(h1.value,h2.value);
for(h of [h1,h2,ha])h.style.background=h.value;
}
*{font-family:monospace;font-size:5vw; }
<label>Color 1 → <input id='h1'></label><br>
<label>Average → <input id='ha'></label><br>
<label>Color 2 → <input id='h2'></label><br>
<label>Type hex colors or <input type='checkbox' id='chk' onclick='auto()' style=' transform: scale(1.5)'checked>Autorandom</label>
回答8:
Here is the function
function avgColor(color1, color2) {
//separate each color alone (red, green, blue) from the first parameter (color1)
//then convert to decimal
let color1Decimal = {
red: parseInt(color1.slice(0, 2), 16),
green: parseInt(color1.slice(2, 4), 16),
blue: parseInt(color1.slice(4, 6), 16)
}
//separate each color alone (red, green, blue) from the second parameter (color2)
//then convert to decimal
let color2Decimal = {
red: parseInt(color2.slice(0, 2), 16),
green: parseInt(color2.slice(2, 4), 16),
blue: parseInt(color2.slice(4, 6), 16),
}
// calculate the average of each color (red, green, blue) from each parameter (color1,color2)
let color3Decimal = {
red: Math.ceil((color1Decimal.red + color2Decimal.red) / 2),
green: Math.ceil((color1Decimal.green + color2Decimal.green) / 2),
blue: Math.ceil((color1Decimal.blue + color2Decimal.blue) / 2)
}
//convert the result to hexadecimal and don't forget if the result is one character
//then convert it to uppercase
let color3Hex = {
red: color3Decimal.red.toString(16).padStart(2, '0').toUpperCase(),
green: color3Decimal.green.toString(16).padStart(2, '0').toUpperCase(),
blue: color3Decimal.blue.toString(16).padStart(2, '0').toUpperCase()
}
//put the colors (red, green, blue) together to have the output
let color3 = color3Hex.red + color3Hex.green + color3Hex.blue
return color3
}
console.log(avgColor("FF33CC", "3300FF"))
// avgColor("FF33CC", "3300FF") => "991AE6"
console.log(avgColor("991AE6", "FF0000"))
// avgColor("991AE6", "FF0000") => "CC0D73"
console.log(avgColor("CC0D73", "0000FF"))
// avgColor("CC0D73", "0000FF") => "6607B9"
To check you can use this link and midpoint 1 then blend https://meyerweb.com/eric/tools/color-blend/#CC0D73:0000FF:1:hex
来源:https://stackoverflow.com/questions/6367010/average-2-hex-colors-together-in-javascript