将十六进制转换为RGBA

134

我的小测试 - http://jsbin.com/pitu/1/edit

我想尝试一下简单的十六进制转换为RGBA。我使用的每个浏览器都默认使用RGB来渲染颜色,因此当使用farbtastic颜色选择器时,我通过获取背景色来生成十六进制值所产生的rgb值(默认=简单转换)来将十六进制值转换为RGB。

我曾试图将)符号替换为, 1),但没有成功,所以我想看看将RGB转换为RGBA会如何工作,但我仍然遇到了困难。

JQuery

$('.torgb').val($('#color').css('background-color'));
$('.torgba').val().replace(/rgb/g,"rgba");
目标是: enter image description here 编辑: TinyColor 是一个很棒的颜色操作 JS 库,它可以满足我所有需求并且更多。我想你们也许想试试!- https://github.com/bgrins/TinyColor

2
TinyColor 是一个非常棒的颜色操作 JS 库,它可以满足我在这里所需的一切以及更多。我想你们可能想要尝试一下! - Michael Schwartz
28个回答

234
//If you write your own code, remember hex color shortcuts (eg., #fff, #000)

function hexToRgbA(hex){
    var c;
    if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){
        c= hex.substring(1).split('');
        if(c.length== 3){
            c= [c[0], c[0], c[1], c[1], c[2], c[2]];
        }
        c= '0x'+c.join('');
        return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+',1)';
    }
    throw new Error('Bad Hex');
}

hexToRgbA('#fbafff')

/*  returned value: (String)
rgba(251,175,255,1)
*/

1
谢谢。像奇迹一样有效。:) - Manprit Singh Sahota
9
易于理解的解决方案,但不支持8位十六进制色彩代码,例如#ff0000aa - supersan
1
如果输入的字符数不是恰好为3或6个,则此方法无法正常工作。 - keeehlan
2
@KehlanKrumme 你有什么例子吗? - Adrien

148

@ElDoRado1239的想法是正确的,但还有一种更简洁的方法:

function hexToRGB(hex, alpha) {
    var r = parseInt(hex.slice(1, 3), 16),
        g = parseInt(hex.slice(3, 5), 16),
        b = parseInt(hex.slice(5, 7), 16);

    if (alpha) {
        return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")";
    } else {
        return "rgb(" + r + ", " + g + ", " + b + ")";
    }
}

hexToRGB('#FF0000', 0.5);


4
注意:这将无法处理十六进制快捷方式,例如 #fff。不过这应该很容易修复! - Matthew Herbst
1
嗯,是的,你必须给函数正确的输入... - AJFarkas
1
非常易读,我比正则表达式更喜欢这个解决方案。 - dahrens
干得好!!不过我要提一点小事。我有一些在字符串中保留逗号和RGBA值之间空格的不好经历(例如:rgba(255, 35, 234, 0.5))。特别是如果您将此值传递给另一个程序,请注意这一点。因为有些程序不接受字符串中的值之间有空格。因此,最好从最终输出中删除这些空格。 - Tharanga
请注意,如果alpha为0,则返回rga。但您可能希望alpha为0。无论如何都很容易修复。 - Mareș Ștefan
显示剩余3条评论

55

ES6用于处理带或不带'#'的6位十六进制字符的函数:

const hex2rgba = (hex, alpha = 1) => {
  const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16));
  return `rgba(${r},${g},${b},${alpha})`;
};

使用方法:

hex2rgba('#af087b', .5)   // returns: rgba(175,8,123,0.5)
hex2rgba('af087b', .5)    // returns: rgba(175,8,123,0.5)
hex2rgba('af087b')        // returns: rgba(175,8,123,1)

由于ArraytoString方法使用,分隔,而输入可以是rrggbbaa hex格式,因此您可以将代码更改为 const rgb = hex.match(...).slice(0,3).map(...) returnn`${rgb},${alpha}`; - Morteza Tourani
1
以下代码还将转换hex2rgba('#369', 0.5);var hex2rgba = (hex, alpha = 1) => { const [r, g, b] = hex.match(hex.length<=4 ? /\w/g : /\w\w/g).map(x => parseInt(x.length<2?${x}${x}: x, 16)); return rgba(${r},${g},${b},${alpha}); }; - Serkan KONAKCI
我建议使用 hex.match(/[0-9A-Fa-f]{2}/g) 来确保输入只包含十六进制字符。 - Barlo

46

清晰易懂的 TypeScript 版本:

hexToRGB(hex: string, alpha: string) {

  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);

  if (alpha) {
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  }

  return `rgb(${r}, ${g}, ${b})`;
}

根据 @AJFarkas 的回答。


3
有时候这个不起作用,在某些情况下会返回 r、g 或/和 b 的 NaN。 - Renascent
对我有用!谢谢 - Saxophonist
else语句应该返回rgb(${r}, ${g}, ${b}),因为它没有alpha通道。 - Amanshu Kataria
@AmanshuKataria 是的,应该没问题。很好发现。 - Chrillewoodz
1
不需要 else {} 因为你在 if 中返回。还可以考虑使用一行代码: return alpha ? \rgba(${r}, ${g}, ${b}, ${alpha})` : `rgb(${r}, ${g}, ${b})`` - Sebastian Voráč

25

任何十六进制模块化方法

主要的挑战在于,截至2018年,现有几种HEX表述方式。传统的6个字符形式,3个字符简写形式以及新的包含字母的4个和8个字符形式。下面的函数可以处理任何HEX形式。

const isValidHex = (hex) => /^#([A-Fa-f0-9]{3,4}){1,2}$/.test(hex)

const getChunksFromString = (st, chunkSize) => st.match(new RegExp(`.{${chunkSize}}`, "g"))

const convertHexUnitTo256 = (hexStr) => parseInt(hexStr.repeat(2 / hexStr.length), 16)

const getAlphafloat = (a, alpha) => {
    if (typeof a !== "undefined") {return a / 255}
    if ((typeof alpha != "number") || alpha <0 || alpha >1){
      return 1
    }
    return alpha
}

export const hexToRGBA = (hex, alpha) => {
    if (!isValidHex(hex)) {throw new Error("Invalid HEX")}
    const chunkSize = Math.floor((hex.length - 1) / 3)
    const hexArr = getChunksFromString(hex.slice(1), chunkSize)
    const [r, g, b, a] = hexArr.map(convertHexUnitTo256)
    return `rgba(${r}, ${g}, ${b}, ${getAlphafloat(a, alpha)})`
}

Alpha可以以下列方式之一提供给函数:

  1. 作为4位或8位十六进制格式的一部分。
  2. 作为介于0-1之间的第二个参数。

输出

    const c1 = "#f80"
    const c2 = "#f808"
    const c3 = "#0088ff"
    const c4 = "#0088ff88"
    const c5 = "#98736"

    console.log(hexToRGBA(c1))   //  rgba(255, 136, 0, 1)
    console.log(hexToRGBA(c2))   //  rgba(255, 136, 0, 0.53125)
    console.log(hexToRGBA(c3))   //  rgba(0, 136, 255, 1)
    console.log(hexToRGBA(c4))   //  rgba(0, 136, 255, 0.53125)
    console.log(hexToRGBA(c5))   //  Uncaught Error: Invalid HEX

    console.log(hexToRGBA(c1, 0.5))   //  rgba(255, 136, 0, 0.5)
    console.log(hexToRGBA(c3, 0.5))   //  rgba(0, 136, 255, 0.5)

2
一些浏览器支持带有不透明度的十六进制颜色,而其他浏览器则不支持。将8位十六进制转换为rgba格式非常有用,因为所有浏览器都支持rgba。 - George
2
@George,谢谢!在创建这个之后,我问自己是否真的需要这样全面的方法。你的反馈很有价值。 - Ben Carp
1
我认为 alpha 计算中可能存在一个小 bug。我认为它应该是:返回 a / 255,否则 FF 就不会返回 1。 - Dustin Kerstein
@DustinKerstein 很好的发现!可能不会造成伤害,但仍应该修复。 - Ben Carp
1
这是最佳答案,而且它在所有单元测试中都能正常工作。 - Menai Ala Eddine - Aladdin

12

如果有帮助,这是一个纯JS解决方案:

function hexToRGB(hex,alphaYes){
 var h = "0123456789ABCDEF";
 var r = h.indexOf(hex[1])*16+h.indexOf(hex[2]);
 var g = h.indexOf(hex[3])*16+h.indexOf(hex[4]);
 var b = h.indexOf(hex[5])*16+h.indexOf(hex[6]);
 if(alphaYes) return "rgba("+r+", "+g+", "+b+", 1)";
 else return "rgb("+r+", "+g+", "+b+")";
}

"alphaYes"是指是否需要透明度,值为"true"或"false"。

预览


在这种情况下,“else”关键字是不必要的。它将返回非字母字符。 - Andy
哦,是的,但这对我来说似乎更加“整洁”。我想这只是个人偏好的问题。 - ElDoRado1239
1
这段代码无法处理小写十六进制(例如 #f0a16e)。我建议先使用 toUpperCasehex 转换为大写。 - philippe_b

11

这里有一个函数,如果您提供了alpha,则返回rgb或rgba。该函数还可以转换短的十六进制颜色代码。

function:

function hexToRgb(hex, alpha) {
   hex   = hex.replace('#', '');
   var r = parseInt(hex.length == 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16);
   var g = parseInt(hex.length == 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16);
   var b = parseInt(hex.length == 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16);
   if ( alpha ) {
      return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')';
   }
   else {
      return 'rgb(' + r + ', ' + g + ', ' + b + ')';
   }
}

例子:

hexToRgb('FF0000');// rgb(255, 0, 0)
hexToRgb('#FF0000');// rgb(255, 0, 0)
hexToRgb('#FF0000', 1);// rgba(255, 0, 0, 1)
hexToRgb('F00');// rgb(255, 0, 0)
hexToRgb('#F00');// rgb(255, 0, 0)
hexToRgb('#F00', 1);// rgba(255, 0, 0, 1)

8

ES6 是一种现代化的解决方案,它不需要使用正则表达式进行错误检查,并且使用常量箭头函数。如果没有给出 alpha 参数,则默认值为 1,对于错误情况会返回 null。

const hexToRGB = (hex, alpha = 1) => {
    let parseString = hex;
    if (hex.startsWith('#')) {parseString = hex.slice(1, 7);}
    if (parseString.length !== 6) {return null;}
    const r = parseInt(parseString.slice(0, 2), 16);
    const g = parseInt(parseString.slice(2, 4), 16);
    const b = parseInt(parseString.slice(4, 6), 16);
    if (isNaN(r) || isNaN(g) || isNaN(b)) {return null;}
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};

注意:该函数在出现错误时返回null。您可以将{return null;}替换为抛出语句:{throw "Not a valid hex color!";},但是这种情况下您应该从try-catch中调用它:
hexToRGB("#3454r5") => null
hexToRGB("#345465") => rgba(52, 84, 101, 1)
hexToRGB("#345465", 0.5) => rgba(52, 84, 101, 0.5)

4

我喜欢 @AJFarkas 的答案并为其添加了支持快捷十六进制颜色(#fff)的功能。

function hexToRGB(hex, alpha) {
    if (!hex || [4, 7].indexOf(hex.length) === -1) {
        return; // throw new Error('Bad Hex');
    }

    hex = hex.substr(1);
    // if shortcuts (#F00) -> set to normal (#FF0000)
    if (hex.length === 3) { 
        hex = hex.split('').map(function(el){ 
              return el + el + '';
            }).join('');
    }

    var r = parseInt(hex.slice(0, 2), 16),
        g = parseInt(hex.slice(2, 4), 16),
        b = parseInt(hex.slice(4, 6), 16);

    if (alpha !== undefined) {
        return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")";
    } else {
        return "rgb(" + r + ", " + g + ", " + b + ")";
    }
}

document.write(hexToRGB('#FF0000', 0.5));
document.write('<br>');
document.write(hexToRGB('#F00', 0.4));


4
一种干净易读的TypeScript方式:(我可以分离类型,但像这样复制和粘贴更容易)
export const hexToRGB = (hex: string, alpha: number | undefined = 1) => {
  hex = hex.toUpperCase();

  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);

  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
 }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接