代码之家  ›  专栏  ›  技术社区  ›  Francesco

JS:从字符串中获取RGBA值

  •  -1
  • Francesco  · 技术社区  · 9 年前

    我正在使用当前代码,如这里所建议的,从“RGB(0,0,0)”之类的字符串中获取RGB值,但也可以是“RGB(0,0,0096)”,所以现在我还需要获取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;
    }
    
    1 回复  |  直到 9 年前
        1
  •  2
  •   T.J. Crowder    5 年前

    您的原始正则表达式已经允许alpha(有四组数字之间带逗号,其中第四组是可选的;还要注意 a rgba 靠近开头是可选的,因为 ? 之后)。你可以通过查看 match[4] :

    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. 但是,如果后面没有数字,则无效 .

    还有几个其他注意事项:

    • 这个代码依赖于我所说的 The Horror of Implicit Globals 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 函数以及我为什么使用它而不是 + / Number 或 parseFloat

    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]
    .作为控制台包装{