JS:从字符串中获取 RGBA 值



我正在使用SO上建议的当前代码,从"rgb(0, 0, 0)"之类的字符串中获取RGB值,但它也可以是"rgb(0, 0, 0,096)",所以现在我还需要获取alpha值

function getRGB(str) {
var match = str.match(/rgba?((d{1,3}), ?(d{1,3}), ?(d{1,3}))?(?:, ?(d(?:.d?))))?/);
arr = [match[1], match[2], match[3]];
return arr;
}

我在下面尝试了这段代码,但它不起作用

function getRGBA(str) {
var match = str.match(/rgba?((d{1,3}), ?(d{1,3}), ?(d{1,3}), ?(d{1,3}))?(?:, ?(d(?:.d?))))?/);
arr = [match[1], match[2], match[3], match[4]];
return arr;
}

您的原始正则表达式已经允许使用 alpha(有四组数字,中间有逗号,其中第四组是可选的;另请注意,rgba开头附近的a是可选的,因为它后面有?)。您可以通过查看match[4]来判断您是否获得了 alpha 版本:

function getRGB(str) {
var match = str.match(/rgba?((d{1,3}), ?(d{1,3}), ?(d{1,3}))?(?:, ?(d(?:.d?))))?/);
arr = [match[1], match[2], match[3]];
if (match[4]) {          // ***
arr.push(match[4]);  // ***
}                        // ***
return arr;
}

严格来说不是你问的,但正则表达式有几个问题会阻止它可靠地检测字符串:

  • 它只允许逗号后的一个空格,但多个空格有效
  • 逗号前不允许任何空格
  • 在 alpha 部分,它允许1.但如果没有.后面的数字,这是无效

其他一些注意事项:

  • 该代码依赖于我所说的隐式全局的恐怖,因为它从不声明arr
  • 代码不会将值转换为数字。我不知道你是否想这样做,但我认为这是值得注意的。
  • 如果字符串与表达式不匹配,该函数将引发错误。也许这就是你想要的,但我想我会把它标记出来。

此表达式可以更好地匹配:

/rgba?((d{1,3})s*,s*(d{1,3})s*,s*(d{1,3})s*(?:)|,s*(d?(?:.d+)?)))/

现场示例:

function num(str) {
str = str.trim();
// Just using + would treat "" as 0
// Using parseFloat would ignore trailing invalid chars
// More: https://stackoverflow.com/questions/28994839/why-does-string-to-number-comparison-work-in-javascript/28994875#28994875
return str === "" ? NaN : +str;
}
function getRGB(str) {
const match = str.match(/rgba?((d{1,3})s*,s*(d{1,3})s*,s*(d{1,3})s*(?:)|,s*(d?(?:.d+)?)))/);
if (!match) {
return null;
}
const arr = [
num(match[1]),
num(match[2]),
num(match[3])
];
if (match[4]) {
arr.push(num(match[4]));
}
return arr;
}
function test(str) {
console.log(str, "=>", JSON.stringify(getRGB(str)))
}
test("rgb(1,2,3,4)");       // [1, 2, 3, 4]
test("rgba(1 , 2, 3, 4)");       // [1, 2, 3, 4]
test("rgba(111   , 22, 33)");    // [111, 22, 33]
test("rgb(111, 22)");           // null (doesn't match)
test("rgb(111, 22   , 33, 1)"); // [111, 22, 33, 1]
test("rgb(111, 22, 33, 1.)");   // null (doesn't match, no digit after .)
test("rgb(111, 22, 33, 1.0)");  // [111, 22, 33, 1]
test("rgb(111, 22, 33, .5)");   // [111, 22, 33, 0.5]
.as-console-wrapper {
max-height: 100% !important;
}

在现代 JavaScript 环境中,我们可以通过使用命名捕获组来简化使用(请参阅num函数的实时示例以及为什么我使用它而不是+/NumberparseFloat):

function getRGB(str) {
const {groups} = str.match(
/rgba?((?<r>d{1,3})s*,s*(?<g>d{1,3})s*,s*(?<b>d{1,3})s*(?:)|,s*(?<a>d?(?:.d+)?)))/
) ?? {groups: null};
if (!groups) {
return null;
}
const arr = [
num(groups.r),
num(groups.g),
num(groups.b)
];
if (groups.a) {
arr.push(num(groups.a));
}
return arr;
}

现场示例:

function num(str) {
str = str.trim();
// Just using + would treat "" as 0
// Using parseFloat would ignore trailing invalid chars
// More: https://stackoverflow.com/questions/28994839/why-does-string-to-number-comparison-work-in-javascript/28994875#28994875
return str === "" ? NaN : +str;
}
function getRGB(str) {
const {groups} = str.match(
/rgba?((?<r>d{1,3})s*,s*(?<g>d{1,3})s*,s*(?<b>d{1,3})s*(?:)|,s*(?<a>d?(?:.d+)?)))/
) ?? {groups: null};
if (!groups) {
return null;
}
const arr = [
num(groups.r),
num(groups.g),
num(groups.b)
];
if (groups.a) {
arr.push(num(groups.a));
}
return arr;
}
function test(str) {
console.log(str, "=>", JSON.stringify(getRGB(str)))
}
test("rgb(1,2,3,4)");       // [1, 2, 3, 4]
test("rgba(1 , 2, 3, 4)");       // [1, 2, 3, 4]
test("rgba(111   , 22, 33)");    // [111, 22, 33]
test("rgb(111, 22)");           // null (doesn't match)
test("rgb(111, 22   , 33, 1)"); // [111, 22, 33, 1]
test("rgb(111, 22, 33, 1.)");   // null (doesn't match, no digit after .)
test("rgb(111, 22, 33, 1.0)");  // [111, 22, 33, 1]
test("rgb(111, 22, 33, .5)");   // [111, 22, 33, 0.5]
.as-console-wrapper {
max-height: 100% !important;
}

最新更新