RGB转十六进制和十六进制转RGB

809

如何将RGB格式的颜色转换为十六进制格式,或将十六进制格式的颜色转换为RGB格式?

例如,将'#0080C0' 转换为 (0, 128, 192)


这里有RGB<->Hex转换,2个十六进制颜色的平均值和随机十六进制颜色的函数。 - ashleedawg
61个回答

1653

注意: rgbToHex 的两个版本都期望 r, g, 和 b 是整数值,因此如果你有非整数值,你需要自己进行四舍五入。

以下代码将执行 RGB 转十六进制并添加所需的零填充:

function componentToHex(c) {
  var hex = c.toString(16);
  return hex.length == 1 ? "0" + hex : hex;
}

function rgbToHex(r, g, b) {
  return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

alert(rgbToHex(0, 51, 255)); // #0033ff

另一种转换方式:

function hexToRgb(hex) {
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}

alert(hexToRgb("#0033ff").g); // "51";

最后,根据@casablanca的答案中讨论的内容和由@cwolves在评论中提出的建议,提供了rgbToHex()的另一种版本:

function rgbToHex(r, g, b) {
  return "#" + (1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1);
}

alert(rgbToHex(0, 51, 255)); // #0033ff

2012年12月3日更新

这是一个可以解析简写十六进制颜色代码(如“#03F”)的hexToRgb()函数版本:

function hexToRgb(hex) {
  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hex = hex.replace(shorthandRegex, function(m, r, g, b) {
    return r + r + g + g + b + b;
  });

  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}

alert(hexToRgb("#0033ff").g); // "51";
alert(hexToRgb("#03f").g); // "51";


12
“<<”是位左移操作符。假设“g”是一个非零整数,“g << 8”的效果相当于将“g”乘以256,并在其十六进制表示的末尾添加零。同样,“r << 16”会添加4个零。添加“1 << 24”(16进制中的1000000)可以确保在使用“slice()”去掉前导的“1”后,十六进制表示左侧有任何必需的零填充。例如,如果“r”和“g”都是零而“b”为51,“((r << 16) + (g << 8) + b).toString(16)”将返回字符串“33”;加上“1 << 24”,你就得到了“1000033”。然后去掉“1”即可。 - Tim Down
4
你的rgbToHex函数不起作用,得到了一个奇怪的结果:#f55b2f00。 - TheCrazyProfessor
@TheCrazyProfessor:针对哪个版本的rgbToHex函数,以及使用了什么输入值? - Tim Down
1
关于最新的 rgbToHex 函数。您需要将传递的 RGB 值强制转换为整数,或者稍微修改 rgbToHex 函数。示例: https://jsfiddle.net/cydqo6wj当前版本: return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);修改后: return "#" + ((1 << 24) + ((+r) << 16) + ((+g) << 8) + (+b)).toString(16).slice(1);在修改后的版本中,我只是在转换成 16 进制之前强制将 RGB 值转换为整数。 - user2977468
1
@RobinMétral:这是由正则表达式匹配的完整字符串。rgb对应于捕获组,这就是我们实际想要的内容。 - Tim Down
显示剩余15条评论

192

hexToRgb的另一种实现方法:

function hexToRgb(hex) {
    var bigint = parseInt(hex, 16);
    var r = (bigint >> 16) & 255;
    var g = (bigint >> 8) & 255;
    var b = bigint & 255;

    return r + "," + g + "," + b;
}

编辑:2017年3月28日 这里是另一种方法,似乎甚至更快

function hexToRgbNew(hex) {
  var arrBuff = new ArrayBuffer(4);
  var vw = new DataView(arrBuff);
  vw.setUint32(0,parseInt(hex, 16),false);
  var arrByte = new Uint8Array(arrBuff);

  return arrByte[1] + "," + arrByte[2] + "," + arrByte[3];
}

编辑:2017年8月11日
经过更多测试,上述新方法并不更快:(。虽然这是一种有趣的替代方式。


70
完美的一行代码:return [r, g, b].join(); - Pavlo
6
或者使用一行代码的解决方案: return [(bigint = parseInt(hex, 16)) >> 16 & 255, bigint >> 8 & 255, bigint & 255].join(); - Pluto
13
我使用这段代码并做了一个小修改 - 在parseInt之前删除非十六进制字符(例如前导的 #):hex = hex.replace(/[^0-9A-F]/gi, ''); - joews
6
不要急于使用简写版本。JSPerf显示,这个答案中的方法是最快的: http://jsperf.com/2014-09-16-hex-to-rgb - Olav Kokovkin
2
小心处理这个,它的输出不可靠。它会让接近黑色的颜色变成深粉色。最好使用顶部答案中的函数。 - Maciej Krawczyk
显示剩余2条评论

146

ECMAScript 6版本的Tim Down答案

将RGB转换为十六进制

const rgbToHex = (r, g, b) => '#' + [r, g, b].map(x => {
  const hex = x.toString(16)
  return hex.length === 1 ? '0' + hex : hex
}).join('')

console.log(rgbToHex(0, 51, 255)); // '#0033ff'

将十六进制转换为RGB

返回一个数组[r,g,b]。也适用于缩写的十六进制三元组,如"#03F"

const hexToRgb = hex =>
  hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i
             ,(m, r, g, b) => '#' + r + r + g + g + b + b)
    .substring(1).match(/.{2}/g)
    .map(x => parseInt(x, 16))

console.log(hexToRgb("#0033ff")) // [0, 51, 255]
console.log(hexToRgb("#03f")) // [0, 51, 255]

奖励:使用 padStart() 方法将 RGB 转换为十六进制

const rgbToHex = (r, g, b) => '#' + [r, g, b]
  .map(x => x.toString(16).padStart(2, '0')).join('')

console.log(rgbToHex(0, 51, 255)); // '#0033ff'

请注意,此答案使用了最新的ECMAScript功能,这些功能不受旧版浏览器支持。如果您希望该代码在所有环境中都能正常工作,应该使用Babel编译代码。


hexToRgb() 可以轻松适应处理 4 和 8 位十六进制 RGBA 表示法:.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,(m, r, g, b) => '#' + r + r + g + g + b + b) 变成了:.replace(/^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])$/i,(m, r, g, b, a) => '#' + r + r + g + g + b + b + a + a) 但是有没有办法使正则表达式可以将 RGBA 中的 A 作为可选的第四个十六进制值来工作呢?这将完全完成功能,使一个正则表达式可以处理十六进制 RGB 和 RGBA。否则就需要两个正则表达式,一个带有 3 个值,另一个带有 4 个值。您必须将第四个值除以 255,以获得 rgba() 的第四个参数。 - Sideways S
const rgbExcludeFirst = rgb.split('rgb(')[1]; const rgbExcludeLast = rgbExcludeFirst.split(')')[0]; const rgbValueArray = rgbExcludeLast.split(','); return `#${rgbValueArray.map((x) => { const valAsInt = parseInt(x, 10); const hex = valAsInt.toString(16); return hex.length === 1 ? `0${hex}` : hex; }).join('')}`; };``` 如果你想传递一个RGB字符串 - Darren Corbett
现代版本的JS的最明智的答案。 - undefined

67

这是我的版本:

function rgbToHex(red, green, blue) {
  const rgb = (red << 16) | (green << 8) | (blue << 0);
  return '#' + (0x1000000 + rgb).toString(16).slice(1);
}

function hexToRgb(hex) {
  const normal = hex.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
  if (normal) return normal.slice(1).map(e => parseInt(e, 16));

  const shorthand = hex.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i);
  if (shorthand) return shorthand.slice(1).map(e => 0x11 * parseInt(e, 16));

  return null;
}

对于 rgb2hex 方法有点困惑。为什么我们要将 rgb 加上 0x1000000,而且为什么最后需要调用 .slice(1) - hackjutsu
因为蓝色的十六进制表示是#FF,我们需要加上0x1000000,这样就变成了#10000FF,然后再去掉第一个“1”。 - FelipeC
这个例子对我也起作用了,当这个页面上的其他例子没有起作用时。 我想把RGB 100, 100, 100转换为HEX,这个页面上的其他例子返回了“#100100100” - 而这个例子则正确地返回了“#646464”。 - TurnerOC

37
function hex2rgb(hex) {
  return ['0x' + hex[1] + hex[2] | 0, '0x' + hex[3] + hex[4] | 0, '0x' + hex[5] + hex[6] | 0];
}

2
巫术!你应该为这个非常酷的一行代码添加一个解释。 - James Harrington
不错!这里有一个相同的东西,只是被压缩了,并返回一个具有属性r,g,b的对象:function hex2rgb(hex){return{r:'0x'+hex[1]+hex[2]|0,g:'0x'+hex[3]+hex[4]|0,b:'0x'+hex[5]+hex[6]|0}} - ashleedawg
非常好。虽然不能与速记一起使用,但是整洁。可以处理哈希而不需要丑陋的下标。 - Adrian Bartholomew

30

我假设你指的是HTML风格的十六进制表示法,即#rrggbb。你的代码几乎是正确的,只是顺序颠倒了。应该改为:

var decColor = red * 65536 + green * 256 + blue;

此外,使用位移操作可能会使代码更易读:

var decColor = (red << 16) + (green << 8) + blue;

@cassablanca - 是的,我错过了一组括号,应该加在你原来的代码周围 :) - user578895
哦,你没有那个 :) 好吧!var hexColor = (red < 16 ? '0' : '') + ((red << 16) + (green << 8) + blue).toString(16); 现在开心了吗?:P - user578895
@cwolves var decColor = (red < 16 ? '00' : '') + ((red << 16) + (green << 8) + blue).toString(16);这样做是可以的,但如果我现在将绿色设为0,我会遇到同样的问题,所以我似乎需要检查所有颜色... - Sindar
@Sindar:你不需要检查绿色和蓝色,只需要检查红色,因为它是领头数字。不过,你可能会发现@Tim Down的答案更简单。 - casablanca
24
var hexColor = ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).substr(1); - user578895
显示剩余15条评论

27

一行代码实现十六进制颜色值转换为RGBA颜色值

支持短格式#fff和长格式#ffffff
支持透明度(alpha通道)。
无论是否有井号都可以工作,不做特别要求。

function hexToRGBA(hex, opacity) {
    return 'rgba(' + (hex = hex.replace('#', '')).match(new RegExp('(.{' + hex.length/3 + '})', 'g')).map(function(l) { return parseInt(hex.length%2 ? l+l : l, 16) }).concat(isFinite(opacity) ? opacity : 1).join(',') + ')';
}

示例:

hexToRGBA('#fff')        ->  rgba(255,255,255,1)  
hexToRGBA('#ffffff')     ->  rgba(255,255,255,1)  
hexToRGBA('#fff', .2)    ->  rgba(255,255,255,0.2)  
hexToRGBA('#ffffff', .2) ->  rgba(255,255,255,0.2)  
hexToRGBA('fff', .2)     ->  rgba(255,255,255,0.2)  
hexToRGBA('ffffff', .2)  ->  rgba(255,255,255,0.2)

hexToRGBA('#ffffff', 0)  ->  rgba(255,255,255,0)
hexToRGBA('#ffffff', .5) ->  rgba(255,255,255,0.5)
hexToRGBA('#ffffff', 1)  ->  rgba(255,255,255,1)

27
尽量编写易读的代码,不要只写一行。无论如何,在生产前压缩代码也没有任何好处。 - Roko C. Buljan
1
这是使用的内容。干得好!除了箭头函数转换之外,我添加的唯一一件事是(hex,opacity = 1)。你的会将0转换为1,这可能不会产生预期结果。 - Adrian Bartholomew
2
这是非常易读的代码。我不同意这种看法。 - Adrian Bartholomew
这是一行很好的代码,易读性也很好。如果你想要多行代码,则可以将其放入格式化程序中。 - Someone Special
不适合初学者。并非每个人都是专家。我需要将这四个值分开,以便进行进一步的计算,并在幻灯片的批量更新中设置页面元素属性,但我无法从这个命令字符串中解析它们。 - aNewb
现在,hex 可以选择性地支持不透明度,#f2c93a42,因此您可以使用以下代码:return 'rgba(' + (hex = hex.replace('#', '')).match(new RegExp('(.{' + hex.length/(hex.length==8?4:3) + '})', 'g')).map(function(l) { return parseInt(hex.length%2 ? l+l : l, 16) }).concat(hex.length===8?'':isFinite(opacity) ? opacity : 1).join(',').replace(/,$/,'') + ')' - frumbert

26

尝试(奖励

let hex2rgb= c=> `rgb(${c.match(/\w\w/g).map(x=>+`0x${x}`)})`
let rgb2hex=c=>'#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``

let hex2rgb= c=> `rgb(${c.match(/\w\w/g).map(x=>+`0x${x}`)})`;
let rgb2hex= c=> '#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``;

// TEST
console.log('#0080C0          -->', hex2rgb('#0080C0'));
console.log('rgb(0, 128, 192) -->', rgb2hex('rgb(0, 128, 192)'));


不错! 我使用以下代码来计算颜色的亮度级别(例如,颜色是深色还是浅色,以便用于识别文本颜色)。 以下是用JavaScript获取亮度的代码:let rgb = color.match(/\w\w/g).map(x=>+\`0x${x}\`); let lum = (rgb[0]*0.299 + rgb[1]*0.587 + rgb[2]*0.114) / 256;lum > 0.5 表示颜色为浅色/亮色。 - Aryo
根据维基百科的说法,亮度(来自HSL)为L = (max(R,G,B) + min(R,G,B))/2 - 但我没有测试过。也许你的公式更基于眼睛的物理特性... @Aryo - Kamil Kiełczewski
1
是的,这个公式并不是真正的亮度公式。使用实际的亮度公式。在相同的亮度水平下,蓝色比绿色/黄色看起来更暗。因此,每个颜色分量都必须进行一些改变。我从这里得到了代码:https://dev59.com/ynI-5IYBdhLWcg3woJ9J#1754281,它根据每个R、G和B颜色的人类感知亮度级别测量亮度级别,并分别加权它们。 - Aryo

23

这段代码接受 #fff 和 #ffffff 变体以及透明度。

function hex2rgb(hex, opacity) {
        var h=hex.replace('#', '');
        h =  h.match(new RegExp('(.{'+h.length/3+'})', 'g'));

        for(var i=0; i<h.length; i++)
            h[i] = parseInt(h[i].length==1? h[i]+h[i]:h[i], 16);

        if (typeof opacity != 'undefined')  h.push(opacity);

        return 'rgba('+h.join(',')+')';
}

16

按位解决方案通常很奇怪。但在这种情况下,我认为它更加优雅。

function hexToRGB(hexColor){
  return {
    red: (hexColor >> 16) & 0xFF,
    green: (hexColor >> 8) & 0xFF,  
    blue: hexColor & 0xFF,
  }
}

使用方法:

const {red, green, blue } = hexToRGB(0xFF00FF)

console.log(red) // 255
console.log(green) // 0
console.log(blue) // 255

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