基于vue3 实现页面自动配色、颜色选择器组件

在网上找的各种颜色的相互转换函数,参考了elementUI的 color-picker组件

function FindRGB(q1, q2, hue) {
    if (hue > 360) hue = hue - 360;
    if (hue < 0) hue = hue + 360;
    if (hue < 60) return (q1 + (q2 - q1) * hue / 60);
    else if (hue < 180) return (q2);
    else if (hue < 240) return (q1 + (q2 - q1) * (240 - hue) / 60);
    else return (q1);
}

function HSLtoRGB(H, S, L) {
    var p1, p2;
    var tempRGB = { R: 0, G: 0, B: 0 }
    L /= 100;
    S /= 100;
    if (L <= 0.5) p2 = L * (1 + S);
    else p2 = L + S - (L * S);
    p1 = 2 * L - p2;
    if (S == 0) {
        tempRGB.R = L;
        tempRGB.G = L;
        tempRGB.B = L;
    }
    else {
        tempRGB.R = FindRGB(p1, p2, H + 120);
        tempRGB.G = FindRGB(p1, p2, H);
        tempRGB.B = FindRGB(p1, p2, H - 120);
    }
    tempRGB.R *= 255;
    tempRGB.G *= 255;
    tempRGB.B *= 255;
    tempRGB.R = Math.round(tempRGB.R);
    tempRGB.G = Math.round(tempRGB.G);
    tempRGB.B = Math.round(tempRGB.B);
    return tempRGB
}

function RGBtoHSL(r, g, b) {
    var Min = 0;
    var Max = 0;
    const HSL = { H: 0, S: 0, L: 0 }
    r = (eval(r) / 51) * .2;
    g = (eval(g) / 51) * .2;
    b = (eval(b) / 51) * .2;

    if (eval(r) >= eval(g))
        Max = eval(r);
    else
        Max = eval(g);
    if (eval(b) > eval(Max))
        Max = eval(b);

    if (eval(r) <= eval(g))
        Min = eval(r);
    else
        Min = eval(g);
    if (eval(b) < eval(Min))
        Min = eval(b);

    HSL.L = (eval(Max) + eval(Min)) / 2;
    if (eval(Max) == eval(Min)) {
        HSL.S = 0;
        HSL.H = 0;
    }
    else {
        if (HSL.L < .5)
            HSL.S = (eval(Max) - eval(Min)) / (eval(Max) + eval(Min));
        if (HSL.L >= .5)
            HSL.S = (eval(Max) - eval(Min)) / (2 - eval(Max) - eval(Min));
        if (r == Max)
            HSL.H = (eval(g) - eval(b)) / (eval(Max) - eval(Min));
        if (g == Max)
            HSL.H = 2 + ((eval(b) - eval(r)) / (eval(Max) - eval(Min)));
        if (b == Max)
            HSL.H = 4 + ((eval(r) - eval(g)) / (eval(Max) - eval(Min)));
    }
    HSL.H = Math.round(HSL.H * 60);
    if (HSL.H < 0) HSL.H += 360;
    if (HSL.H >= 360) HSL.H -= 360;
    HSL.S = Math.round(HSL.S * 100);
    HSL.L = Math.round(HSL.L * 100);
    return HSL
}
//计算辅助色
function getSecColor(r, g, b) {
    const { H, S, L } = RGBtoHSL(r, g, g)
    if (H > 120 && H < 290) {//cold
        if (Math.abs(210 - (H + 30)) < Math.abs(210 - (H - 30))) {
            return HSLtoRGB(H + 30, S, L)
        } else {
            return HSLtoRGB(H + 30, S, L)
        }

    } else {
        if (Math.abs(30 - (H + 30)) < Math.abs(30 - (H - 30))) {
            return HSLtoRGB(H + 30, S, L)
        } else {
            return HSLtoRGB(H + 30, S, L)
        }
    }
}

function getContrastColor(r, g, b) {
    const hsl = RGBtoHSL(r, g, b)
    hsl.H = (hsl.H + 180) % 360
    return HSLtoRGB(hsl.H, hsl.S, hsl.L)
}

function getLightenColor(r, g, b) {
    const { H, S, L } = RGBtoHSL(r, g, b)
    return HSLtoRGB(H, S, Math.min(100, L + 5))
}

function getDarkcolor(r, g, b) {
    const { H, S, L } = RGBtoHSL(r, g, b)
    return HSLtoRGB(H, S, Math.max(0, L - 5))
}
function setvar(key, value) {
    document.body.style.setProperty(key, value)
}
function rgb2hex(rgb) {
    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2).toUpperCase();
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
function rgba2hex(r, g, b, a) {
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2).toUpperCase();
    }
    return "#" + hex(r) + hex(g) + hex(b)+hex(256*a-1);
}

function hsv2hsl(hue, sat, val) {
    return [
        hue,
        (sat * val / ((hue = (2 - sat) * val) < 1 ? hue : 2 - hue)) || 0,
        hue / 2
    ];
};

// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
// 
const isOnePointZero = function (n) {
    return typeof n === 'string' && n.indexOf('.') !== -1 && parseFloat(n) === 1;
};

const isPercentage = function (n) {
    return typeof n === 'string' && n.indexOf('%') !== -1;
};

// Take input from [0, n] and return it as [0, 1]
const bound01 = function (value, max) {
    if (isOnePointZero(value)) value = '100%';

    const processPercent = isPercentage(value);
    value = Math.min(max, Math.max(0, parseFloat(value)));

    // Automatically convert percentage into number
    if (processPercent) {
        value = parseInt(value * max, 10) / 100;
    }

    // Handle floating point rounding errors
    if ((Math.abs(value - max) < 0.000001)) {
        return 1;
    }

    // Convert into [0, 1] range if it isn't already
    return (value % max) / parseFloat(max);
};

const INT_HEX_MAP = { 10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F' };

const toHex = function ({ r, g, b }) {
    const hexOne = function (value) {
        value = Math.min(Math.round(value), 255);
        const high = Math.floor(value / 16);
        const low = value % 16;
        return '' + (INT_HEX_MAP[high] || high) + (INT_HEX_MAP[low] || low);
    };

    if (isNaN(r) || isNaN(g) || isNaN(b)) return '';

    return '#' + hexOne(r) + hexOne(g) + hexOne(b);
};

const HEX_INT_MAP = { A: 10, B: 11, C: 12, D: 13, E: 14, F: 15 };

const parseHexChannel = function (hex) {
    if (hex.length === 2) {
        return (HEX_INT_MAP[hex[0].toUpperCase()] || +hex[0]) * 16 + (HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1]);
    }

    return HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1];
};

const hsl2hsv = function (hue, sat, light) {
    sat = sat / 100;
    light = light / 100;
    let smin = sat;
    const lmin = Math.max(light, 0.01);
    let sv;
    let v;

    light *= 2;
    sat *= (light <= 1) ? light : 2 - light;
    smin *= lmin <= 1 ? lmin : 2 - lmin;
    v = (light + sat) / 2;
    sv = light === 0 ? (2 * smin) / (lmin + smin) : (2 * sat) / (light + sat);

    return {
        h: hue,
        s: sv * 100,
        v: v * 100
    };
};

// `rgbToHsv`
// Converts an RGB color value to HSV
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
// *Returns:* { h, s, v } in [0,1]
const rgb2hsv = function (r, g, b) {
    r = bound01(r, 255);
    g = bound01(g, 255);
    b = bound01(b, 255);

    const max = Math.max(r, g, b);
    const min = Math.min(r, g, b);
    let h, s;
    let v = max;

    const d = max - min;
    s = max === 0 ? 0 : d / max;

    if (max === min) {
        h = 0; // achromatic
    } else {
        switch (max) {
            case r:
                h = (g - b) / d + (g < b ? 6 : 0);
                break;
            case g:
                h = (b - r) / d + 2;
                break;
            case b:
                h = (r - g) / d + 4;
                break;
        }
        h /= 6;
    }

    return { h: h * 360, s: s * 100, v: v * 100 };
};

// `hsvToRgb`
// Converts an HSV color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
const hsv2rgb = function (h, s, v) {
    h = bound01(h, 360) * 6;
    s = bound01(s, 100);
    v = bound01(v, 100);

    const i = Math.floor(h);
    const f = h - i;
    const p = v * (1 - s);
    const q = v * (1 - f * s);
    const t = v * (1 - (1 - f) * s);
    const mod = i % 6;
    const r = [v, q, p, p, t, v][mod];
    const g = [t, v, v, q, p, p][mod];
    const b = [p, p, t, v, v, q][mod];

    return {
        r: Math.round(r * 255),
        g: Math.round(g * 255),
        b: Math.round(b * 255)
    };
};

export default {
    FindRGB,
    HSLtoRGB,
    RGBtoHSL,
    getSecColor,
    getContrastColor,
    getLightenColor,
    getDarkcolor,
    setvar,
    rgb2hex,
    hsv2hsl,
    toHex,
    parseHexChannel,
    hsl2hsv,
    rgb2hsv,
    hsv2rgb,
    rgba2hex
}

组件的实现 w-theme.vue



使用方法。


import wTheme from './components/w-theme.vue';


你可能感兴趣的:(前端,vue,前端)