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

引言
在 CSS、HTML、WPF XAML 以及许多其他文件中,颜色都以以下形式指定:
- 颜色名称 - 例如 red
- '#' 后跟 6 位十六进制值 - 例如 #123456
- '#' 后跟 3 位十六进制值 - 例如 #123,系统会将其展开为 #112233
- 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 文件包含以下部分:
- 两个文本亮度计算函数
- 一个文本解析器,用于解析输入文本、验证它并查找 RGB 通道值
- 一个显示函数,用于将方块插入 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 同时拥有 substr
和 substring
函数。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 日