如何获得十六进制颜色值而不是 RGB 值?

IT技术 javascript jquery colors hex rgb
2021-01-14 07:15:41

使用以下 jQuery 将获得元素背景颜色的 RGB 值:

$('#selector').css('backgroundColor');

有没有办法获得十六进制值而不是RGB?

6个回答

TLDR

将这个干净的单行函数与rgbrgba支持一起使用:

const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`

2021 更新答案

自从我最初回答这个问题以来已经过去了很长时间。然后很酷的 ECMAScript 5 和 2015+ 特性在浏览器上大量可用,如箭头函数Array.mapString.padStart模板字符串所以现在可以写一个单行了rgb2hex

const rgb2hex = (rgb) => `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`

// Use as you wish...
console.log(rgb2hex('rgb(0,0,0)'))
console.log(rgb2hex('rgb(255, 255, 255)'))
console.log(rgb2hex('rgb(255,0,0)'))
console.log(rgb2hex('rgb(38, 170, 90)'))

基本上,我们使用正则表达式来获取rgb字符串中的每个数字slice(1)只获取数字(第一个结果match是完整的字符串本身),map遍历每个数字,每次迭代转换为Numberwith parseInt,然后返回为十六进制String(通过 base-16 转换),如果需要,通过padStart. 最后,只是join每个转换/调整位为唯一的String开始'#'

当然,我们可以毫不费力地将它扩展为单行rgba2hex

const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`

// Now it doesn't matter if 'rgb' or 'rgba'...
console.log(rgba2hex('rgb(0,0,0)'))
console.log(rgba2hex('rgb(255, 255, 255)'))
console.log(rgba2hex('rgb(255,0,0)'))
console.log(rgba2hex('rgb(38, 170, 90)'))
console.log(rgba2hex('rgba(255, 0, 0, 0.5)'))
console.log(rgba2hex('rgba(0,255,0,1)'))
console.log(rgba2hex('rgba(127,127,127,0.25)'))

就是这样。但是,如果您想深入了解旧式 JavaScript 世界,请继续阅读。


2010 年的原始答案

这是我根据@Matt 建议编写的更清洁的解决方案:

function rgb2hex(rgb) {
    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

某些浏览器已将颜色返回为十六进制(从 Internet Explorer 8 及以下版本开始)。如果您需要处理这些情况,只需在函数内附加一个条件,就像@gfrobenius 建议的那样:

function rgb2hex(rgb) {
    if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;

    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

如果您正在使用 jQuery 并想要更完整的方法,您可以使用自 jQuery 1.4.3 以来可用的CSS Hooks,正如我在回答这个问题时所展示的:Can I force jQuery.css("backgroundColor") returns on hexadecimal format?

对不起,我不同意。跨浏览器功能总是比需要基于浏览器检测执行的功能好。Op 要求转换$('#selector').css('backgroundColor')为十六进制,而不是将 rgb 值转换为十六进制。而在 IE8 上,$('#selector').css('backgroundColor')已经是十六进制的,所以必须处理。就是这样。不要生我的气:)
2021-03-14 07:15:41
@Ghigo,抱歉,您错了。IE8已经获取当前的风格时,这种方式返回颜色为十六进制:document.getElementById("your_id").currentStyle["backgroundColor"]rgb2hex()不需要这个功能这是我上面建议的使用 CSS Hooks 的 jQuery 插件,它已经完成了所有验证以在不同浏览器中恢复颜色:stackoverflow.com/questions/6177454/...
2021-03-15 07:15:41
做这些家伙,我添加到rgb2hex()函数中的一个简单的衬垫,谢谢@ErickPetru!信不信由你,我必须编码回 IE7。使用.css('backgroundColor')和本机obj.style.backgroundColorIE7 & 8 将返回十六进制,而不是 RGB,因此我将其添加为rgb2hex()所提供答案中函数的第一行,以便它一直工作到 IE7:/* IE7&8 will return hex, so no need to run this function if it is already hex. */ if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb.substring(1, 7); //I'm doing a subtring here because I do not want the leading # symbol希望有所帮助。
2021-03-16 07:15:41
我建议大家:看看我在这里的回复,看看使用jQuery CSS Hooks的改进版本
2021-03-21 07:15:41
@Ghigo,我认为您误解了:如果您在以十六进制返回的浏览器中,则不应使用此功能。此函数将 RGB 转换为 HEX,仅此而已。当它不是 RGB 时不要使用它。您需要一个更完整的解决方案(它检测值是否已经为 RGB,如@Jim-F 所提出的)这一事实并没有改变这个解决方案提供的正是 OP 所要求的这一事实。你的反对毫无意义,抱歉。
2021-03-28 07:15:41
var hexDigits = new Array
        ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"); 

//Function to convert rgb color to hex format
function rgb2hex(rgb) {
 rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
 return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

function hex(x) {
  return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
 }

来源

+1,您可以使用 Number.toString(16) - 至少对于每个十六进制数字(如果小于 16,则用 0 填充)
2021-03-15 07:15:41
@SlimFadi 你的正则表达式不起作用,因为你没有转义括号。一旦修复,它也会匹配无效值,例如 rgb(0, 0, 0, 0) 和 rgba(0, 0 ,0) ,但对于此目的,这应该不是问题。
2021-03-26 07:15:41
-1. 正如 orip 所提到的,您可以使用 toString(16)。因其他低效率而被否决。如果您要在每次函数调用时声明 hexDigits,至少在 rgb2hex 的函数体(不是 hex 的函数体)中执行此操作,因此每次调用 rgb2hex 时,数组不会重新定义 3 次。还要学习使用'var',这样你就不会污染全局范围。
2021-04-01 07:15:41
如果你真的想学究,你可以让正则表达式更加宽容:rgb.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i)但是,给定的正则表达式旨在处理使用 jQuery 时浏览器给出的格式,并且没有不同的空格或captilisation 一致性你在谈论。您也可以使用相同的正则表达式,并在匹配 rgb 之前删除所有空格并转换为小写。PS 你的小提琴示例:'rgb(10, 128,)' 我认为测试是不合理的
2021-04-01 07:15:41
这种方法似乎不太能容忍不同的空格或大写。jsfiddle.net/Xotic750/pSQ7d
2021-04-04 07:15:41

大多数浏览器在使用时似乎会返回 RGB 值:

$('#selector').css('backgroundColor');

只有 IE(到目前为止只测试了 6 个)返回十六进制值。

为了避免 IE 中的错误消息,您可以将函数包装在 if 语句中:

function rgb2hex(rgb) {
     if (  rgb.search("rgb") == -1 ) {
          return rgb;
     } else {
          rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
          function hex(x) {
               return ("0" + parseInt(x).toString(16)).slice(-2);
          }
          return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); 
     }
}
这个比其他大多数都好用,因为 Jim 将 rgba 考虑在内,这是 Safari(至少在 Mac OS X 上)使用的。谢谢,吉姆!
2021-03-12 07:15:41
很好的解决方案。请注意,函数返回小写字母,即#ff5544 而不是#FF5544。
2021-03-21 07:15:41
这个正则表达式也将支持上述解决方案中的 aplha 通道 rgb = rgb.match(/^rgba?((\d+),\s*(\d+),\s*(\d+)(?:,\s*) (0\.\d+))?)$/);
2021-03-31 07:15:41

更新了@ErickPetru 以获得 rgba 兼容性:

function rgb2hex(rgb) {
    rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

如果定义了,我更新了正则表达式以匹配 alpha 值,但不使用它。

只是为了完整性:我正在研究一个可以导出到 PowerPoint 的东西(不要问......),它接受 alpha 通道的十六进制字符串上的第四个字节,所以可以像这样使用它: return hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]) /* Add the alpha channel if it exists */ + (rgb[5] !== undefined ? hex(Math.round(rgb[5] * 255)) : ''); 此外,我正在删除该#符号以使其与最终用途无关(0x例如,可以获取输出并在其前面加上它,或者不加前缀)。希望它可以帮助某人!
2021-03-31 07:15:41

这是一个不使用 jQuery 的 ES6 one liner:

var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => parseInt(color).toString(16).padStart(2, '0')).join('');
此答案不适用于小数字,例如parseInt('0').toString(16) # => '0',如果字符串是单个数字,则必须填充该字符串parseInt('0').toString(16).padStart(2, '0') => '00'
2021-03-28 07:15:41
谢谢,这帮助我将其合并到 Wordpress 页面中,该页面去除了之前答案中的正则表达式反斜杠。
2021-04-02 07:15:41