Average 2 hex colors together in javascript

强颜欢笑 提交于 2021-02-05 16:42:06

问题


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 enter image description here

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.

$.xcolor.average(color, color)




回答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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!