65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript 颜色查看器

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (4投票s)

2011 年 5 月 22 日

CPOL

4分钟阅读

viewsIcon

27252

downloadIcon

260

用于查看 HTML/CSS 颜色的网页

screen.jpg

引言

在 CSS、HTML、WPF XAML 以及许多其他文件中,颜色都以以下形式指定:

  1. 颜色名称 - 例如 red
  2. '#' 后跟 6 位十六进制值 - 例如 #123456
  3. '#' 后跟 3 位十六进制值 - 例如 #123,系统会将其展开为 #112233
  4. RGB 颜色 - 例如 RGB(255, 0, 0)

我曾多次发现,尤其是在阅读他人代码时,我需要弄清楚这些数字到底代表什么颜色。因此,我开发了一个 JavaScript 颜色查看器,您可以在本地计算机上下载并使用它。在线版本也可以在此 找到。

背景

颜色由用户动态输入。程序无法提前知道它会是什么颜色。但是,程序必须为前景文本选择一种颜色。无论我们选择哪种颜色,它都可能与背景色相同,导致我们无法看到它。因此,我们需要使用至少两种对比色来显示文本。在程序中,我们使用黑色或白色作为文本颜色。并通过一个函数根据其 RGB 值计算背景色的亮度。该函数基于 这篇文章,该文章引用了 这篇文章

我们也可以在颜色块下方显示文本,并仅使用黑色作为文本颜色。但我认为这会让这个程序变得相当无聊。

Using the Code

该程序包含 3 个文件:一个 HTML 文件、一个 JavaScript 文件和一个 CSS 文件。HTML 文件很简单,如下所示:

<div id="controls">
    <span>Color</span>
    <input type="text" id="txt" size="30"/>
    <input type="button" id="btn" value="Display"/>
</div>
<div id="message">Input is invalid!</div>
<div id="view"></div>

当用户输入无效颜色时,会显示 "message""view" 是插入颜色块的位置。

JavaScript 文件包含以下部分:

  1. 两个文本亮度计算函数
  2. 一个文本解析器,用于解析输入文本、验证它并查找 RGB 通道值
  3. 一个显示函数,用于将方块插入 HTML DOM 树

从 RGB 通道计算颜色的 JavaScript 代码如下:

function getTextColor2(red, green, blue) {
    var brightness = ((red * 299) + (green * 587) + (blue * 114)) / 1000;
    if(brightness < 125) { //background is dark
        return 'white';
    } else {
        return 'black';
    }
}

在我看来,对于程序员来说,知道这个函数的存在比知道它为什么有效更重要。但是,如果您确实想知道原因,请参考前面提到的文章以了解详情。

您也可以从十六进制值计算亮度:

function getTextColor(hex) {
    if(hex.length == 3) {
        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
    }
    var red = parseInt(hex.substring(0, 2), 16);
    var green = parseInt(hex.substring(2, 4), 16);
    var blue = parseInt(hex.substring(4, 6), 16);

    return getTextColor2(red, green, blue);
}  

3 位十六进制颜色值,如 #123,会被展开为 #112233。JavaScript 的 parseInt 函数可以接受第二个参数,即要解析的数字的基数(基数)。基数可以是 2 到 36 之间的任何数字。在本例中,我们使用 16 来解析十六进制字符串。

JavaScript 同时拥有 substrsubstring 函数。substr 不在 ECMAScript 标准中。所以我们在这里不使用它。但是,substr 被大多数 Web 浏览器支持。这两个 string 函数的用法如下:

  • s.substr(start, length)
  • s.substr(start) // 直到结尾
  • s.substring(start, end) // 2 个索引

区别在于 substr 从一个索引到某个长度,而 substring 从索引到索引。我记住它的方式是:substring 中的 "ing"index(索引)。

文本解析器使用以下正则表达式来解析输入:

var regHex6 = /^#?([a-f\d]{6})$/;
var regHex3 = /^#?([a-f\d]{3})$/;
var regRgb = /^rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/;

十六进制输入的开头 "#" 是可选的,这是为了方便像我一样懒惰的人。 \d{1,3} 表示一个数字重复 1、2 或 3 次。

文本解析器还需要一个巨大的字典 "standardColors" 来检查所有标准颜色。此字典位于 JavaScript 文件的末尾,此处未列出。解析器将检查颜色是否存在以及颜色的十六进制值,以便程序可以计算文本颜色。

以下是文本解析器的代码,它返回一个具有 2 个属性的对象。一个属性 text 将显示为前景色。另一个属性 textColor 将是黑色或白色,它是根据前面提到的亮度函数计算得出的,将用作文本颜色。将使用三个正则表达式逐个匹配输入,如果没有匹配的,函数将假定输入是颜色名称。然后将检查 "standardColors" 字典。

function parseInput(text) {
    var textLower = text.trim().toLowerCase();
    var result = textLower.match(regHex6);
    var hex;

    if(result) {
        hex = result[1];
        return {
            text: '#' + hex,
            textColor: getTextColor(hex)
        };
    }
    result = textLower.match(regHex3);
    if(result) {
        hex = result[1];
        return {
            text: '#' + hex,
            textColor: getTextColor(hex)
        };
    }
    result = textLower.match(regRgb);
    if(result) {
        var red = result[1];
        var green = result[2];
        var blue = result[3];
        if(red < 256 && green < 256 && blue < 256) {
            return {
                text: 'RGB(' + red + ', ' + green + ', ' + blue + ')',
                textColor: getTextColor2(red, green, blue)
            };
        }
    }
    hex = standardColors[textLower];
    if(hex) return {
                text: textLower,
                textColor: getTextColor(hex)
            };
    return null;
}

最后,在用户输入颜色后,以下函数将一个颜色块插入 HTML DOM。

var displayColor = function() {
    var result = parseInput(txt.value);

    if(result) {
        msg.style.display = "none";
        view.innerHTML =
            '<div class="' + result.textColor + '">' +
                '<div class="inner">' +
                    '<span>' + result.text + '</span>' +
                '</div>' +
            '</div>' + view.innerHTML;
        view.firstChild.style.backgroundColor = result.text;
        txt.value = "";

    } else {
        msg.style.display = "block";
    }
};

view 是 HTML 文件中的一个 <div> 元素。以下行将一个新块添加到 view 中。

view.innerHTML = [something] + view.innerHTML;

插入的 <div> 元素将根据 CSS 文件进行显示,CSS 文件如下所示:

#view > div {
    width: 100px;
    height: 100px;
    margin: 5px;
    float: left;
    display: table;
    text-align: center;
    font-weight: bold;
    font-size: 16px;
    font-family: "Courier New";
}

.white {
    color: white;
}

.black {
    color: black;
    border: 1px solid #eee;
}

.inner {
    display: table-cell;
    vertical-align: middle;
}

为了在垂直方向上居中文本,外层 <div> 使用 display: table; 样式,内层 <div> 使用 display: table-cell;vertical-align: middle; 样式。这在大多数浏览器中都有效。

关注点

displayColor 函数进行了大量的 string 加法运算。在第一个草稿中,我使用了 string 格式化函数,这使得代码更加整洁。它在大多数浏览器中都有效。但是,出于未知原因,Internet Explorer 就是不喜欢它。我的 string 格式化函数如下所示:

String.prototype.format = function() {
    var result = this;
    for(arg in arguments) {
        result = result.replace("{" + arg + "}", arguments[arg]);
    }
    return result;
};

如果您知道为什么此函数在 Internet Explorer 中不起作用,请告诉我。

历史

  • 第一个版本:2011 年 5 月 19 日
© . All rights reserved.