如何将颜色在RGB格式转换为十六进制格式,反之亦然?

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


当前回答

HEX转RGB (ES6) +测试[2022]

convertHexToRgb.ts:

/**
 * RGB color regexp
 */
export const RGB_REG_EXP = /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/;

/**
 * HEX color regexp
 */
export const HEX_REG_EXP = /^#?(([\da-f]){3}|([\da-f]){6})$/i;

/**
 * Converts HEX to RGB.
 *
 * Color must be only HEX string and must be:
 *  - 7-characters starts with "#" symbol ('#ffffff')
 *  - or 6-characters without "#" symbol ('ffffff')
 *  - or 4-characters starts with "#" symbol ('#fff')
 *  - or 3-characters without "#" symbol ('fff')
 *
 * @function { color: string => string } convertHexToRgb
 * @return { string } returns RGB color string or empty string
 */
export const convertHexToRgb = (color: string): string => {
    const errMessage = `
    Something went wrong while working with colors...
    
    Make sure the colors provided to the "PieDonutChart" meet the following requirements:
    
    Color must be only HEX string and must be 
    7-characters starts with "#" symbol ('#ffffff')
    or 6-characters without "#" symbol ('ffffff')
    or 4-characters starts with "#" symbol ('#fff')
    or 3-characters without "#" symbol ('fff')
    
    - - - - - - - - -
    
    Error in: "convertHexToRgb" function
    Received value: ${color}
  `;

    if (
        !color
        || typeof color !== 'string'
        || color.length < 3
        || color.length > 7
    ) {
        console.error(errMessage);
        return '';
    }

    const replacer = (...args: string[]) => {
        const [
            _,
            r,
            g,
            b,
        ] = args;

        return '' + r + r + g + g + b + b;
    };

    const rgbHexArr = color
        ?.replace(HEX_REG_EXP, replacer)
        .match(/.{2}/g)
        ?.map(x => parseInt(x, 16));

    /**
     * "HEX_REG_EXP.test" is here to create more strong tests
     */
    if (rgbHexArr && Array.isArray(rgbHexArr) && HEX_REG_EXP.test(color)) {
        return `rgb(${rgbHexArr[0]}, ${rgbHexArr[1]}, ${rgbHexArr[2]})`;
    }

    console.error(errMessage);
    return '';
};

我正在使用Jest进行测试

color.spec.ts

describe('function "convertHexToRgb"', () => {
    it('returns a valid RGB with the provided 3-digit HEX color: [color = \'fff\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();
        const rgb = convertHexToRgb('fff');

        expect(RGB_REG_EXP.test(rgb)).toBeTruthy();
        expect(consoleErrorMocked).not.toHaveBeenCalled();
    });

    it('returns a valid RGB with the provided 3-digit HEX color with hash symbol: [color = \'#fff\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();
        const rgb = convertHexToRgb('#fff');

        expect(RGB_REG_EXP.test(rgb)).toBeTruthy();
        expect(consoleErrorMocked).not.toHaveBeenCalled();
    });

    it('returns a valid RGB with the provided 6-digit HEX color: [color = \'ffffff\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();
        const rgb = convertHexToRgb('ffffff');

        expect(RGB_REG_EXP.test(rgb)).toBeTruthy();
        expect(consoleErrorMocked).not.toHaveBeenCalled();
    });

    it('returns a valid RGB with the provided 6-digit HEX color with the hash symbol: [color = \'#ffffff\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();
        const rgb = convertHexToRgb(TEST_COLOR);

        expect(RGB_REG_EXP.test(rgb)).toBeTruthy();
        expect(consoleErrorMocked).not.toHaveBeenCalled();
    });

    it('returns an empty string when the provided value is not a string: [color = 1234]', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();

        // @ts-ignore
        const rgb = convertHexToRgb(1234);

        expect(rgb).toBe('');
        expect(consoleErrorMocked).toHaveBeenCalledTimes(1);
    });

    it('returns an empty string when the provided color is too short: [color = \'FF\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();

        const rgb = convertHexToRgb('FF');

        expect(rgb).toBe('');
        expect(consoleErrorMocked).toHaveBeenCalledTimes(1);
    });

    it('returns an empty string when the provided color is too long: [color = \'#fffffff\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();

        const rgb = convertHexToRgb('#fffffff');

        expect(rgb).toBe('');
        expect(consoleErrorMocked).toHaveBeenCalledTimes(1);
    });

    it('returns an empty string when the provided value is looks like HEX color string but has invalid symbols: [color = \'#fffffp\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();
        const rgb = convertHexToRgb('#fffffp');

        expect(rgb).toBe('');
        expect(consoleErrorMocked).toHaveBeenCalledTimes(1);
    });

    it('returns an empty string when the provided value is invalid: [color = \'*\']', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();

        const rgb = convertHexToRgb('*');

        expect(rgb).toBe('');
        expect(consoleErrorMocked).toHaveBeenCalledTimes(1);
    });

    it('returns an empty string when the provided value is undefined: [color = undefined]', () => {
        expect.assertions(2);

        const { consoleErrorMocked }  = mockConsole();

        // @ts-ignore
        const rgb = convertHexToRgb(undefined);

        expect(rgb).toBe('');
        expect(consoleErrorMocked).toHaveBeenCalledTimes(1);
    });
});

测试结果:

function "convertHexToRgb"
    √ returns a valid RGB with the provided 3-digit HEX color: [color = 'fff']
    √ returns a valid RGB with the provided 3-digit HEX color with hash symbol: [color = '#fff']
    √ returns a valid RGB with the provided 6-digit HEX color: [color = 'ffffff']
    √ returns a valid RGB with the provided 6-digit HEX color with the hash symbol: [color = '#ffffff']
    √ returns an empty string when the provided value is not a string: [color = 1234]
    √ returns an empty string when the provided color is too short: [color = 'FF']
    √ returns an empty string when the provided color is too long: [color = '#fffffff']
    √ returns an empty string when the provided value is looks like HEX color string but has invalid symbols: [color = '#fffffp']
    √ returns an empty string when the provided value is invalid: [color = '*']
    √ returns an empty string when the provided value is undefined: [color = undefined]

和mockConsole:

export const mockConsole = () => {
  const consoleError = jest.spyOn(console, 'error').mockImplementationOnce(() => undefined);
  return { consoleError };
};

其他回答

我假设您指的是html风格的十六进制符号,即#rrggbb。你的代码几乎是正确的,只是顺序颠倒了。它应该是:

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

此外,使用位移位可能会让它更容易阅读:

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

我的hex2rbg版本:

接受短十六进制,如#fff 算法容量为o(n),应该比使用正则表达式快。如字符串。替换字符串。分裂,字符串。匹配等。 使用固定空间。 支持rgb和rgba。

如果你使用的是IE8,你可能需要删除hex.trim()。

如。

hex2rgb('#fff') //rgb(255,255,255) 
hex2rgb('#fff', 1) //rgba(255,255,255,1) 
hex2rgb('#ffffff') //rgb(255,255,255)  
hex2rgb('#ffffff', 1) //rgba(255,255,255,1)

代码:

function hex2rgb (hex, opacity) {
    hex = hex.trim();
    hex = hex[0] === '#' ? hex.substr(1) : hex;
    var bigint = parseInt(hex, 16), h = [];
    if (hex.length === 3) {
        h.push((bigint >> 4) & 255);
        h.push((bigint >> 2) & 255);
    } else {
        h.push((bigint >> 16) & 255);
        h.push((bigint >> 8) & 255);
    }
    h.push(bigint & 255);
    if (arguments.length === 2) {
        h.push(opacity);
        return 'rgba('+h.join()+')';
    } else {
        return 'rgb('+h.join()+')';
    }
}

哇。这些答案都不能处理分数的边缘情况,等等。当r, g, b为零时,位移版本也不起作用。

这是一个可以处理r g b是小数的版本。它对颜色之间的插值很有用,所以我也包括了这段代码。但它仍然不能处理r, g, b在0-255范围之外的情况

/**
 * Operates with colors.
 * @class Q.Colors
 */
 Q.Color = {
    /**
     * Get a color somewhere between startColor and endColor
     * @method toHex
     * @static
     * @param {String|Number} startColor 
     * @param {String|Number} endColor 
     * @param {String|Number} fraction 
     * @returns {String} a color as a hex string without '#' in front
     */
    toHex: function (r, g, b) {
        return [r, g, b].map(x => {
            const hex = Math.round(x).toString(16)
            return hex.length === 1 ? '0' + hex : hex
          }).join('');
    },
    /**
     * Get a color somewhere between startColor and endColor
     * @method between
     * @static
     * @param {String|Number} startColor 
     * @param {String|Number} endColor 
     * @param {String|Number} fraction 
     * @returns {String} a color as a hex string without '#' in front
     */
    between: function(startColor, endColor, fraction) {
        if (typeof startColor === 'string') {
            startColor = parseInt(startColor.replace('#', '0x'), 16);
        }
        if (typeof endColor === 'string') {
            endColor = parseInt(endColor.replace('#', '0x'), 16);
        }
        var startRed = (startColor >> 16) & 0xFF;
        var startGreen = (startColor >> 8) & 0xFF;
        var startBlue = startColor & 0xFF;
        var endRed = (endColor >> 16) & 0xFF;
        var endGreen = (endColor >> 8) & 0xFF;
        var endBlue = endColor & 0xFF;
        var newRed = startRed + fraction * (endRed - startRed);
        var newGreen = startGreen + fraction * (endGreen - startGreen);
        var newBlue = startBlue + fraction * (endBlue - startBlue);
        return Q.Color.toHex(newRed, newGreen, newBlue);
    },
    /**
     * Sets a new theme-color on the window
     * @method setWindowTheme
     * @static
     * @param {String} color in any CSS format, such as "#aabbcc"
     * @return {String} the previous color
     */
    setWindowTheme: function (color) {
        var meta = document.querySelector('meta[name="theme-color"]');
        var prevColor = null;
        if (meta) {
            prevColor = meta.getAttribute('content');
        }
        if (color) {
            if (!meta) {
                meta = document.createElement('meta');
                meta.setAttribute('name', 'theme-color');
            }
            meta.setAttribute('content', color);
        }
        return prevColor;
    },
    /**
     * Gets the current window theme color
     * @method getWindowTheme
     * @static
     * @param {String} color in any CSS format, such as "#aabbcc"
     * @return {String} the previous color
     */
    getWindowTheme: function () {
        var meta = document.querySelector('meta[name="theme-color"]');
        return meta.getAttribute('content');
    }
}

(2017) SIMPLE ES6组合箭头函数

我忍不住要把这个分享给那些可能正在使用ES6编写一些现代函数/复合js的人。下面是我在一个颜色模块中使用的一些光滑的单行程序,它为数据可视化做颜色插值。

注意,这根本不处理alpha通道。

const arrayToRGBString = rgb => `rgb(${rgb.join(',')})`;
const hexToRGBArray = hex => hex.match(/[A-Za-z0-9]{2}/g).map(v => parseInt(v, 16));
const rgbArrayToHex = rgb => `#${rgb.map(v => v.toString(16).padStart(2, '0')).join('')}`;
const rgbStringToArray = rgb => rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).splice(1, 3)
  .map(v => Number(v));
const rgbStringToHex = rgb => rgbArrayToHex(rgbStringToArray(rgb));

顺便说一句,如果你喜欢这种风格/语法,我写了一个全彩色模块(modern-color),你可以从npm中获取。我这样做,所以我可以使用道具getter转换和解析几乎任何东西(Color.parse(anything))。如果你和我一样对颜色很敏感的话,值得一看。

你想要这样的东西吗?

function RGB2HTML(red, green, blue)
{
    return '#' + red.toString(16) +
           green.toString(16) +
           blue.toString(16);
}

alert(RGB2HTML(150, 135, 200));

显示# 9687 c8