好吧,我想我会把这个扔出去让大家思考一下。
给定一个 函数 (用 javascript 编写),它需要两个格式化为十六进制颜色的字符串(ex #FF0000)
返回十六进制颜色,它是传递的两种颜色的平均值。
function averageColors(firstColor,secondColor)
{
...
return avgColor;
}
--编辑--
平均值定义为
如果传递的颜色是黄色,第二个颜色是浅紫色,则返回的颜色将是中橙色
新答案(2024)
color-mix
CSS 属性,我们希望能够更灵活可靠地做到这一点:
export const mixColors = (
colorA: string,
colorB: string,
mix = 0.5,
space = "hsl",
) => {
const style = `color-mix(in ${space}, ${colorA}, ${colorB} ${100 * mix}%)`;
const div = document.createElement("div");
if (!window.matchMedia(`@supports (color: ${style}`)) return colorA;
div.style.color = style;
document.body.append(div);
const [r = 0, g = 0, b = 0] = window
.getComputedStyle(div)
.color.split(/\s/)
.map(parseFloat)
.filter((value) => !Number.isNaN(value));
div.remove();
const floatToHex = (value: number) =>
Math.round(255 * value)
.toString(16)
.padStart(2, "0");
return "#" + [r, g, b].map(floatToHex).join("");
};
现在我们可以做任何颜色空间,而不仅仅是我的旧答案所做的 RGB。我们可以做命名颜色,如
maroon
或任何其他有效的 CSS 颜色。
这还会检查
color-mix
支持,并回退到仅返回第一种颜色。
注意:这是基于我在 Chrome/Firefox/Safari 中的测试,我观察到
getComputedStyle
会计算,例如,color-mix(in hsl, red, orange 10%)
值可小至 color(srgb 1 0.0647058 0)
形式。我已经找到了这两个资源,但我有点不清楚是否存在边缘情况,它不会采用这种格式:
getComputedStyle 规范中是否指定了颜色格式? https://github.com/w3c/csswg-drafts/issues/7302
旧答案
一种按指定百分比混合两种十六进制颜色的快速/肮脏/方便/ES6 方法:
// 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));
其中
amount
应该是 0
到 1
,其中 0
恰好是 colorA
,1
恰好是 colorB
,0.5
是“中点”。
我讨厌听起来像破烂的 jQuery 记录,但是is已经有一个jQuery 插件了。
如果你不想打扰很多不必要的东西,只需要几行 POJS:
// 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('');
}
}());
对我来说就像是家庭作业,但这是我的线索。
取 R、G 和 B 的每个十六进制值,并对它们进行平均。 如有必要,请转换为十进制进行数学计算。
函数 d2h(d) {return d.toString(16).padStart(2,'0');}
函数 h2d(h) {返回 parseInt(h,16);}
然后返回一个包含三个元素的串联值的字符串。
这是一组紧凑的相关(相互依赖)函数:
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 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));}
function rndHex(){return'#'+('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6);}
// 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>
这是我的功能,希望对你有帮助。
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);}}
参加这个聚会已经很晚了,但我个人正在寻找一种方法来平均未定义数量的十六进制值。根据答案@RobG,我想出了这个。当然,您添加的颜色越多,它们就会变得越棕色/灰色,但是,也许这会有所帮助!
/**
* 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"
这是函数
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"
要检查,您可以使用此链接和中点 1,然后混合 https://meyerweb.com/eric/tools/color-blend/#CC0D73:0000FF:1:hex