android经常用到的一个小工具颜色计算器

我们经常会遇到几个颜色场景:

  1. 使用颜色,尤其是figma,经常需要计算百分比;
  2. 我们经常需要选择满意的颜色,不太知道当前的RGB值或者HEX值;
  3. 通过颜色取色器,比如系统自带的或者飞书带的,只知道其中一种;
  4. 有时候想把ARGB转成一个类似的不带透明度的颜色值,那么就可以通过该工具后重新取色即可。

就是一个简单的html网页,保存后,使用浏览器打开:复制如下代码:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>颜色转换器</title>
    <style>
        body {
            font-family: sans-serif;
            padding: 20px;
        }
        .main-container {
            padding: 20px;
            border: 1px solid #ccc;
            border-radius: 4px;
            display: flex;
            flex-direction: column;
            gap: 20px;
            max-width: 800px;
        }
        .vbox {
            display: flex;
            flex-direction: column;
        }
        .hbox {
            display: flex;
            flex-direction: row;
            align-items: center;
            gap: 10px;
        }
        .title-label-big {
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 10px;
        }
        .normal-label {
            font-size: 14px;
            margin-bottom: 5px;
        }
        /* Controls */
        input[type="color"] {
            width: 80px;
            height: 30px;
            cursor: pointer;
        }
        .circle {
            width: 88px; /* radius 44 * 2 */
            height: 88px;
            border-radius: 50%;
            border: 1px solid black;
            background-color: white;
            margin-left: 50px;
            transition: background-color 0.3s;
        }
        .stack-pane {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 140px;
            height: 30px;
            margin-bottom: 5px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        .white-bg { background-color: white; }
        .gray-bg { background-color: #808080; }
        .black-bg { background-color: black; }
        
        .title-label-big-bold {
            font-weight: bold;
            font-size: 14px;
        }
        .white-bg .title-label-big-bold { color: black; }
        .gray-bg .title-label-big-bold { color: white; }
        .black-bg .title-label-big-bold { color: white; }

        /* Standard Inputs */
        input[type="text"] {
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 16px;
            outline: none;
            transition: border-color 0.2s;
        }
        input[type="text"]:focus {
            border-color: #2196F3;
        }
        
        button {
            padding: 6px 16px;
            cursor: pointer;
            background-color: #2196F3;
            color: white;
            border: none;
            border-radius: 4px;
            font-weight: bold;
            box-shadow: 0 2px 4px rgba(0,0,0,0.2);
            transition: background-color 0.2s, box-shadow 0.2s;
        }
        button:hover {
            background-color: #1976D2;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }
        button:active {
            box-shadow: 0 1px 2px rgba(0,0,0,0.2);
            transform: translateY(1px);
        }

        .copy-btn {
            background-color: #4CAF50; /* Green */
        }
        .copy-btn:hover {
            background-color: #45a049;
        }

        select {
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 4px;
            outline: none;
            font-size: 16px;
        }

        /* Margins helpers */
        .ml-20 { margin-left: 20px; }
        .ml-50 { margin-left: 50px; }
        .mt-30 { margin-top: 30px; }
        
        .powered-by {
            font-size: 12px;
            color: #eeeeee;
            margin-left: 10px; /* Gap after title */
            align-self: flex-end; /* Align bottom */
            margin-bottom: 8px; /* Fine tune vertical alignment */
        }
    </style>
</head>
<body>

<div class="main-container">
    <div class="hbox" style="align-items: flex-end;">
        <div class="title-label-big" style="margin-bottom: 0;">颜色转换器</div>
        <div class="powered-by">Powered by Allan</div>
    </div>

    <!-- HBox 1: 取色卡 -->
    <div class="hbox" style="margin-top: 10px; margin-left: 10px;">
        <div class="vbox">
            <span class="normal-label">取色卡</span>
            <input type="color" id="colorPicker" value="#ffffff">
        </div>

        <div id="circle" class="circle"></div>

        <div class="vbox ml-50">
            <div class="stack-pane white-bg">
                <span id="exampleLabel" class="title-label-big-bold">纯色改文字颜色</span>
            </div>
            <div class="stack-pane gray-bg">
                <span id="exampleLabel2" class="title-label-big-bold">灰色改文字颜色</span>
            </div>
            <div class="stack-pane black-bg">
                <span id="exampleLabel3" class="title-label-big-bold">黑色改文字颜色</span>
            </div>
        </div>

        <div class="vbox ml-50">
            <div id="exampleBg1" class="stack-pane">
                <span class="title-label-big-bold" style="color: black;">黑色文字改背景</span>
            </div>
            <div id="exampleBg2" class="stack-pane">
                <span class="title-label-big-bold" style="color: white;">白色文字改背景</span>
            </div>
        </div>
    </div>

    <!-- HBox 2: 设置1 -->
    <div class="hbox mt-30" style="margin-left: 10px;">
        <span class="normal-label">设置1: 十六位制</span>
        <input type="text" id="hexColorInput" class="ml-20" style="width: 88px;">
        <button id="enterForHexBtn" class="ml-20">确定</button>
        <button id="copyHexBtn" class="ml-20 copy-btn">复制</button>
    </div>

    <!-- HBox 3: 设置2 -->
    <div class="hbox mt-30" style="margin-left: 10px;">
        <span class="normal-label" style="margin-top: 10px;">设置2:ARGB制</span>
        
        <select id="chooseAlphaModeCombo" style="width: 77px;">
            <option value="ARGB">ARGB</option>
            <option value="RGB">RGB</option>
            <option value="AHEX">AHEX</option>
        </select>

        <div class="vbox" style="margin-left: 8px;">
            <input type="text" id="sA" style="width: 36px; display: none;">
        </div>

        <div class="vbox" style="margin-left: 8px;">
            <input type="text" id="fHex" style="width: 80px; display: none;">
        </div>

        <div id="boxR" class="vbox" style="margin-left: 8px;">
            <input type="text" id="fR" style="width: 36px;">
        </div>

        <div id="boxG" class="vbox" style="margin-left: 8px;">
            <input type="text" id="fG" style="width: 36px;">
        </div>

        <div id="boxB" class="vbox" style="margin-left: 8px;">
            <input type="text" id="fB" style="width: 36px;">
        </div>

        <button id="enterForRGBBtn">确定</button>
    </div>

    <!-- HBox 4: 标签行 -->
    <div class="hbox" style="margin-left: 10px; margin-top: -12px;">
        <span style="width: 195px;"></span> <!-- Spacer for label + combo (77+8+20 = 105) -->
        
        <div style="width: 36px; text-align: center; margin-left: 8px;">
            <span id="fALabel" class="normal-label" style="display: none; font-size: 13px; font-weight: bold;">A</span>
        </div>

        <div style="width: 80px; text-align: center; margin-left: 8px;">
            <span id="fHexLabel" class="normal-label" style="display: none; font-size: 13px; font-weight: bold;">Hex</span>
        </div>

        <div id="labelR" style="width: 36px; text-align: center; margin-left: 38px;">
            <span class="normal-label" style="font-size: 13px; font-weight: bold;">R</span>
        </div>

        <div id="labelG" style="width: 36px; text-align: center; margin-left: 15px;">
            <span class="normal-label" style="font-size: 13px; font-weight: bold;">G</span>
        </div>

        <div id="labelB" style="width: 36px; text-align: center; margin-left: 18px;">
            <span class="normal-label" style="font-size: 13px; font-weight: bold;">B</span>
        </div>
    </div>

    <span id="errorInfo" class="normal-label" style="color: red;"></span>
</div>

<script>
    // 简单的交互逻辑:颜色选择器改变圆的颜色
    const colorPicker = document.getElementById('colorPicker');
    const circle = document.getElementById('circle');
    const hexInput = document.getElementById('hexColorInput');
    
    // 文本元素(修改文字颜色)
    const exampleLabel = document.getElementById('exampleLabel');
    const exampleLabel2 = document.getElementById('exampleLabel2');
    const exampleLabel3 = document.getElementById('exampleLabel3');

    // 背景元素(修改背景颜色)
    const exampleBg1 = document.getElementById('exampleBg1');
    const exampleBg2 = document.getElementById('exampleBg2');

    // 预览更新函数:仅更新圆、文本和背景颜色,不更新输入框
    function applyPreviewColors(color) {
        circle.style.backgroundColor = color;
        
        // 更新前3个文本的文字颜色
        exampleLabel.style.color = color;
        exampleLabel2.style.color = color;
        exampleLabel3.style.color = color;

        // 更新后2个文本的背景颜色
        exampleBg1.style.backgroundColor = color;
        exampleBg2.style.backgroundColor = color;
    }

    // 原始 updateColors 保留给取色器使用(会更新输入框)
    function updateColors(color) {
        applyPreviewColors(color);
        hexInput.value = color;

        // 同步填充设置2的所有输入框
        // color 格式为 #RRGGBB
        const r = parseInt(color.substring(1, 3), 16);
        const g = parseInt(color.substring(3, 5), 16);
        const b = parseInt(color.substring(5, 7), 16);
        const a = 255;

        document.getElementById('fR').value = r;
        document.getElementById('fG').value = g;
        document.getElementById('fB').value = b;
        document.getElementById('sA').value = a;
        
        // 同步 Hex 输入框 (AHEX 模式用)
        const toHex = (n) => {
            const h = n.toString(16).toUpperCase();
            return h.length === 1 ? '0' + h : h;
        };
        document.getElementById('fHex').value = toHex(r) + toHex(g) + toHex(b);
    }

    colorPicker.addEventListener('input', (e) => {
        updateColors(e.target.value);
    });

    // 示例:十六进制输入改变颜色
    document.getElementById('enterForHexBtn').addEventListener('click', () => {
        let hex = hexInput.value.trim();
        if (hex.startsWith('#')) {
            hex = hex.substring(1);
        }

        let r, g, b, a = 255;
        let valid = false;

        // 正则校验:6位 hex (RRGGBB) 或 8位 hex (AARRGGBB)
        if (/^[0-9A-Fa-f]{6}$/.test(hex)) {
            r = parseInt(hex.substring(0, 2), 16);
            g = parseInt(hex.substring(2, 4), 16);
            b = parseInt(hex.substring(4, 6), 16);
            valid = true;
        } else if (/^[0-9A-Fa-f]{8}$/.test(hex)) {
            // Android 格式:AARRGGBB
            a = parseInt(hex.substring(0, 2), 16);
            r = parseInt(hex.substring(2, 4), 16);
            g = parseInt(hex.substring(4, 6), 16);
            b = parseInt(hex.substring(6, 8), 16);
            valid = true;
        }

        if (valid) {
            // 1. 联动预览 (使用 CSS rgba)
            const cssColor = `rgba(${r}, ${g}, ${b}, ${a / 255})`;
            applyPreviewColors(cssColor);

            // 2. 联动取色卡 (仅 RGB,格式 #RRGGBB)
            // 辅助函数:转 hex 补 0
            const toHex = (n) => {
                const h = n.toString(16);
                return h.length === 1 ? '0' + h : h;
            };
            colorPicker.value = '#' + toHex(r) + toHex(g) + toHex(b);

            // 3. 填充设置2
            document.getElementById('fR').value = r;
            document.getElementById('fG').value = g;
            document.getElementById('fB').value = b;
            
            // 如果当前模式是 ARGB,则填充 A;否则仅在内存中保留(这里直接填充即可,反正隐藏了也不影响)
            document.getElementById('sA').value = a;

            // 补充:填充 AHEX 模式的 Hex 输入框
            document.getElementById('fHex').value = toHex(r) + toHex(g) + toHex(b);

        } else {
            alert('请输入有效的十六进制颜色代码!\n格式支持:RRGGBB 或 AARRGGBB (例如 #FFFFFF 或 FF800000)');
        }
    });

    // 复制按钮点击逻辑
    document.getElementById('copyHexBtn').addEventListener('click', () => {
        const hex = hexInput.value.trim();
        if (hex) {
            navigator.clipboard.writeText(hex).then(() => {
                alert('已复制到剪贴板: ' + hex);
            }).catch(err => {
                console.error('无法复制文本: ', err);
                // 降级处理
                const tempInput = document.createElement('input');
                tempInput.value = hex;
                document.body.appendChild(tempInput);
                tempInput.select();
                document.execCommand('copy');
                document.body.removeChild(tempInput);
                alert('已复制到剪贴板: ' + hex);
            });
        } else {
            alert('没有内容可复制');
        }
    });

    // 示例:ARGB/RGB 切换显示
    const combo = document.getElementById('chooseAlphaModeCombo');
    const sA = document.getElementById('sA');
    const fALabel = document.getElementById('fALabel');
    
    // AHEX模式相关元素
    const fHex = document.getElementById('fHex');
    const fHexLabel = document.getElementById('fHexLabel').parentElement; // Parent div
    const boxR = document.getElementById('boxR');
    const boxG = document.getElementById('boxG');
    const boxB = document.getElementById('boxB');
    const labelR = document.getElementById('labelR');
    const labelG = document.getElementById('labelG');
    const labelB = document.getElementById('labelB');
    const labelA = document.getElementById('fALabel').parentElement; // Parent div

    combo.addEventListener('change', (e) => {
        const val = e.target.value;
        // 重置所有显示
        sA.style.display = 'none';
        labelA.style.display = 'none';
        fHex.style.display = 'none';
        fHexLabel.style.display = 'none';
        
        boxR.style.display = 'flex';
        boxG.style.display = 'flex';
        boxB.style.display = 'flex';
        labelR.style.display = 'block';
        labelG.style.display = 'block';
        labelB.style.display = 'block';

        if (val === 'ARGB') {
            sA.style.display = 'block';
            labelA.style.display = 'block';
            document.getElementById('fALabel').style.display = 'inline'; // Ensure text is visible
        } else if (val === 'AHEX') {
            // AHEX模式:显示 A 和 Hex,隐藏 RGB
            sA.style.display = 'block';
            labelA.style.display = 'block';
            document.getElementById('fALabel').style.display = 'inline';
            
            fHex.style.display = 'block';
            fHexLabel.style.display = 'block';
            document.getElementById('fHexLabel').style.display = 'inline';

            boxR.style.display = 'none';
            boxG.style.display = 'none';
            boxB.style.display = 'none';
            labelR.style.display = 'none';
            labelG.style.display = 'none';
            labelB.style.display = 'none';
        }
    });
    
    // 初始化触发一次以隐藏A
    combo.dispatchEvent(new Event('change'));

    // 设置2(ARGB/RGB)确定按钮点击逻辑
    document.getElementById('enterForRGBBtn').addEventListener('click', () => {
        const mode = document.getElementById('chooseAlphaModeCombo').value;
        const rStr = document.getElementById('fR').value.trim();
        const gStr = document.getElementById('fG').value.trim();
        const bStr = document.getElementById('fB').value.trim();
        let aStr = document.getElementById('sA').value.trim();

        let r, g, b, a = 255;
        const toHex = (n) => {
            const h = n.toString(16).toUpperCase();
            return h.length === 1 ? '0' + h : h;
        };
        const isValid = (n) => !isNaN(n) && n >= 0 && n <= 255;

        // 辅助函数:处理 Alpha 输入(支持百分比)
        // 返回 [value, isPercent]
        // 如果是百分比,解析为 0-255 并返回
        // 如果是普通数值,解析为 0-255 并返回
        // 如果无效,返回 null
        const parseAlpha = (str) => {
            str = str.trim();
            if (str.endsWith('%')) {
                const p = parseFloat(str.substring(0, str.length - 1));
                if (isNaN(p) || p < 0 || p > 100) return null;
                return Math.round((p / 100) * 255);
            } else {
                const n = parseInt(str, 10);
                if (isNaN(n) || n < 0 || n > 255) return null;
                return n;
            }
        };

        // AHEX 模式处理
        if (mode === 'AHEX') {
            const hexStr = document.getElementById('fHex').value.trim();
            
            if (!aStr || !hexStr) {
                return; // 任意为空不工作
            }
            
            // 校验 A (支持百分比)
            const parsedA = parseAlpha(aStr);
            if (parsedA === null) {
                alert('Alpha数值必须在 0-255 之间,或 0%-100%');
                return;
            }
            a = parsedA;
            // 将转换后的 A 填回去(如果是百分比输入,转成 0-255)
            document.getElementById('sA').value = a;

            // 校验 Hex (#RRGGBB 或 RRGGBB)
            let cleanHex = hexStr;
            if (cleanHex.startsWith('#')) {
                cleanHex = cleanHex.substring(1);
            }
            if (!/^[0-9A-Fa-f]{6}$/.test(cleanHex)) {
                alert('Hex必须是 RRGGBB 格式 (例如 #FF0000)');
                return;
            }

            r = parseInt(cleanHex.substring(0, 2), 16);
            g = parseInt(cleanHex.substring(2, 4), 16);
            b = parseInt(cleanHex.substring(4, 6), 16);
            
            // 填充其他输入框以便切换模式时数据同步 (可选)
            document.getElementById('fR').value = r;
            document.getElementById('fG').value = g;
            document.getElementById('fB').value = b;

        } else {
            // ARGB / RGB 模式处理
            // 基础非空校验
            if (!rStr || !gStr || !bStr) {
                return; // 任意为空不工作
            }
            if (mode === 'ARGB' && !aStr) {
                return; // ARGB模式下A为空也不工作
            }

            // 解析数值
            r = parseInt(rStr, 10);
            g = parseInt(gStr, 10);
            b = parseInt(bStr, 10);

            // 数值范围校验 (0-255)
            if (!isValid(r) || !isValid(g) || !isValid(b)) {
                alert('RGB数值必须在 0-255 之间');
                return;
            }

            if (mode === 'ARGB') {
                const parsedA = parseAlpha(aStr);
                if (parsedA === null) {
                    alert('Alpha数值必须在 0-255 之间,或 0%-100%');
                    return;
                }
                a = parsedA;
                // 将转换后的 A 填回去
                document.getElementById('sA').value = a;
            }
        }

        // 1. 联动预览
        const cssColor = `rgba(${r}, ${g}, ${b}, ${a / 255})`;
        applyPreviewColors(cssColor);

        // 2. 联动取色卡 (仅 RGB)
        colorPicker.value = '#' + toHex(r) + toHex(g) + toHex(b);

        // 3. 反向填充设置1 (#AARRGGBB 或 #RRGGBB)
        // 注意:AHEX模式最终也是输出 AARRGGBB 格式到设置1
        if (mode === 'ARGB' || mode === 'AHEX') {
            hexInput.value = '#' + toHex(a) + toHex(r) + toHex(g) + toHex(b);
        } else {
            hexInput.value = '#' + toHex(r) + toHex(g) + toHex(b);
        }
    });
</script>

</body>
</html>
相关推荐
郭优秀的笔记2 小时前
html鼠标悬浮提示功能
android·javascript·html
_OP_CHEN4 小时前
【前端开发之HTML】(三)HTML 常见标签(下):图文、链接与实战,解锁网页交互新姿势!
前端·html·交互·前端开发·网页开发·界面美化
lkbhua莱克瓦2419 小时前
JavaScript核心语法
开发语言·前端·javascript·笔记·html·ecmascript·javaweb
0思必得01 天前
[Web自动化] Selenium中Select元素操作方法
前端·python·selenium·自动化·html
@大迁世界1 天前
停止使用 innerHTML:3 种安全渲染 HTML 的替代方案
开发语言·前端·javascript·安全·html
大猫会长1 天前
css中,由基准色提取其他变体
前端·javascript·html
@zulnger1 天前
爬虫库之 requests_html,json
爬虫·html·json
seabirdssss2 天前
《bootstrap is not defined 导致“获取配置详情失败”?一次前端踩坑实录》
前端·bootstrap·html
我是伪码农2 天前
轮播图案例
css·html·css3