React Native 使用两种颜色的十六进制码混合

xpszyzbs  于 2023-08-07  发布在  React
关注(0)|答案(3)|浏览(116)

我正在制作一个react原生应用程序,并试图使用它们的十六进制码将两种或多种颜色混合在一起,然后得到结果的颜色和它的十六进制码。
例如,在每种颜色具有相同比例的情况下,混合颜色:#4285F4 + #EA4335 + #FBBC05 = #SomeColorHexcode。是否有算法可以用来获得结果颜色的十六进制码?
我看了一些旧文章,似乎有一个解决方案:Mixing two colors "naturally" in javascript。但是这篇文章中的主要解决方案似乎使用了jquery,react native不支持jquery。此外,这个问题是在7年前提出的,我想知道现在是否有更好的算法用于混合颜色。
谢谢你,谢谢

zbsbpyhn

zbsbpyhn1#

原则

1.你把颜色值
1.你把CSS颜色值转换成整数
1.你取每个RGB值的中间

let color1 = document.getElementById('color1')
let color2 = document.getElementById('color2')
let colormixed = document.getElementById('colormixed')
let button = document.getElementById('mix')

// this function takes an integer and converts it in a 2 digit hexadecimal number
function componentToHex(c) {
  var hex = c.toString(16);
  return hex.length == 1 ? "0" + hex : hex;
}

// this function takes an array of 3 RGB integer values and converts this array into a CSS color, like this: #AAAAA
function rgbToHex([r, g, b]) {
  return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

// the regex is separating the value into groups of 2 characters, these characters being letters from 'a' to 'f' and digits, that is to say hexadecimal numbers. 
function convert(color) {
  return /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color.value).map(x=>parseInt('0x'+x)).slice(1, 4)
}

button.addEventListener("click", function() {
  // we get the two colors and convert them in integer arrays
  let [c1,c2]= [color1,color2].map(x=>convert(x))

  // this variable will be the array of the mixed color
  let cm = []

  // we take the middle of each RGB value between the two colors
  c1.forEach((c,i) => cm.push(parseInt((c1[i]+c2[i])/2)))

  // we convert the value into a CSS value
  colormixed.value = rgbToHex(cm)
});

个字符
exec的解释如下:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

短码,多种颜色

document.getElementById('add').addEventListener("click", function() {
  let newColor = document.createElement("input")
  newColor.type = 'color'
  newColor.className = 'color'
  document.getElementById('colors').appendChild(newColor)
})

document.getElementById('mix').addEventListener("click", function() {
  document.getElementById('colormixed').value = '#'+Array.from(document.getElementsByClassName('color')).map(x=>/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(x.value).map(y=>parseInt('0x'+y)).slice(1, 4)).reduce((a,b)=>a.map( (num, i) => (num + b[i]))).map(x=>parseInt(x/Array.from(document.getElementsByClassName('color')).length).toString(16).padStart(2, '0')).join('')
});
<div id="colors">
  <header>
    <input type="button" id="mix" value="Mix" />
    <input type="button" id="add" value="Add" />
  </header>
  <input type="color" class="color" value="#ffffff" />
  <input type="color" class="color" value="#000000" />
</div>

<label for"colormixed">Result:</label> <input type="color" id="colormixed"/>

的字符串

一行程序的解释

它包含了所有的颜色:

Array.from(document.getElementsByClassName('color'))


对于每个元素,我们采用CSS颜色代码,并将RGB值分开:

.map(x=>/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(x.value)


对于其中的每个元素,我们将每个十六进制数转换为整数:

.map(y=>parseInt('0x'+y))


我们只取RGB三元组:

.slice(1, 4)


然后我们对所有RGB数组求和:

.reduce((a,b)=>a.map( (num, i) => (num + b[i])))


我们将每个RGB求和值除以颜色总数:

.map(x=>parseInt(x/Array.from(document.getElementsByClassName('color')).length)


我们将每个值转换回十六进制:

.toString(16)


当只有一个数字时,不要忘记添加“0”:

.padStart(2, '0')


我们将RGB数组转换为字符串:

.join('')


我们把“#”放在前面:

'#' +


这就是你的调色机。

igsr9ssn

igsr9ssn2#

我相信这段代码产生的结果与前面的答案相同,但希望它更清楚地说明它是如何工作的。

console.log(mix_hexes('#3890b9', '#f6ff00')); // #8cc46f

function hex2dec(hex) {
  return hex.replace('#', '').match(/.{2}/g).map(n => parseInt(n, 16));
}

function rgb2hex(r, g, b) {
  r = Math.round(r);
  g = Math.round(g);
  b = Math.round(b);
  r = Math.min(r, 255);
  g = Math.min(g, 255);
  b = Math.min(b, 255);
  return '#' + [r, g, b].map(c => c.toString(16).padStart(2, '0')).join('');
}

function rgb2cmyk(r, g, b) {
  let c = 1 - (r / 255);
  let m = 1 - (g / 255);
  let y = 1 - (b / 255);
  let k = Math.min(c, m, y);
  c = (c - k) / (1 - k);
  m = (m - k) / (1 - k);
  y = (y - k) / (1 - k);
  return [c, m, y, k];
}

function cmyk2rgb(c, m, y, k) {
  let r = c * (1 - k) + k;
  let g = m * (1 - k) + k;
  let b = y * (1 - k) + k;
  r = (1 - r) * 255 + .5;
  g = (1 - g) * 255 + .5;
  b = (1 - b) * 255 + .5;
  return [r, g, b];
}

function mix_cmyks(...cmyks) {
  let c = cmyks.map(cmyk => cmyk[0]).reduce((a, b) => a + b, 0) / cmyks.length;
  let m = cmyks.map(cmyk => cmyk[1]).reduce((a, b) => a + b, 0) / cmyks.length;
  let y = cmyks.map(cmyk => cmyk[2]).reduce((a, b) => a + b, 0) / cmyks.length;
  let k = cmyks.map(cmyk => cmyk[3]).reduce((a, b) => a + b, 0) / cmyks.length;
  return [c, m, y, k];
}

function mix_hexes(...hexes) {
  let rgbs = hexes.map(hex => hex2dec(hex)); 
  let cmyks = rgbs.map(rgb => rgb2cmyk(...rgb));
  let mixture_cmyk = mix_cmyks(...cmyks);
  let mixture_rgb = cmyk2rgb(...mixture_cmyk);
  let mixture_hex = rgb2hex(...mixture_rgb);
  return mixture_hex;
}

字符串

jdzmm42g

jdzmm42g3#

我喜欢@GirkovArpa的答案,但没有必要去cmyk着色,它不支持混合#000000。这里有一个函数,它混合了两个六进制,并且可以选择接受混合比。
对于JavaScript,删除类型注解

function hex2dec(hex: string) {
    const matched = hex.replace('#', '').match(/.{2}/g)
    if (!matched) throw new Error('Invalid hex string');
    return matched.map(n => parseInt(n, 16));
}

function rgb2hex(r: number, g: number, b: number) {
    r = Math.round(r);
    g = Math.round(g);
    b = Math.round(b);
    r = Math.min(r, 255);
    g = Math.min(g, 255);
    b = Math.min(b, 255);
    return '#' + [r, g, b].map(c => c.toString(16).padStart(2, '0')).join('');
}

export function mixHexes(hex1: string, hex2: string, ratio: number = 0.5) {
    if (ratio > 1 || ratio < 0) throw new Error('Invalid ratio');
    const [r1, g1, b1] = hex2dec(hex1);
    const [r2, g2, b2] = hex2dec(hex2);
    const r = Math.round(r1 * ratio + r2 * (1 - ratio));
    const g = Math.round(g1 * ratio + g2 * (1 - ratio));
    const b = Math.round(b1 * ratio + b2 * (1 - ratio));
    return rgb2hex(r, g, b);
}

字符串
使用方法:

console.log(mixHexes('#3890b9', '#f6ff00', 0.7));

相关问题