如何创建仅具有绿色、蓝色、橙色和金色值的颜色?
How can I create a color with values for green, blue, orange, and gold only?
如果知道红色、绿色和蓝色的 "weights",就可以使用 class 来创建一种颜色,比如
.blaRGB {
color: rgb(128, 128, 128)
}
.blaHSL {
color: hsl(33%, 34%, 33%)
}
并像这样在 HTML 中使用它:
<p class="blaRGB">BLA RGB</p>
<p class="blaHSL">BLA HSL</p>
根据上面显示的值,blaRGB
是暗灰色,blaHSL
是白色。
但是如果要表示其他颜色的组合,例如绿色、蓝色、橙色和金色,该怎么办?
有没有一种方法可以使用如下所示的符号来定义此类颜色?
.CyndiLauper {
color: truecolors(24, 13, 11, 12)
}
或者用 color: gbog(24, 13, 11, 12)
其中 gbog
中的字母分别代表绿色、蓝色、橙色和金色?
目的是根据上面的 CSS 定义,HTML
<p class="CyndiLauper">These are your True Colors, shining through!</p>
将以这四种颜色的加权组合显示文本。
我相信使用绿色、蓝色、橙色和金色的 RGB 值进行一些复杂的数学运算是可能的,但我不知道如何进行。
更新
我意识到我最初忽略的问题的关键组成部分是 "What exactly do you mean by green, blue, orange, and gold"?
为了回答这个问题,根据官方 "True Colors" website,并使用 ColorZilla 浏览器插件,这些颜色的 RGB 值为:
green = 15, 167, 73
blue = 0, 152, 215
orange = 243, 123, 38
gold = 255, 230, 101
(在我看来,它们实际上更像是森林绿、道奇蓝、红橙色和黄色。)
不,你不能。这是一个 link 到 W3 Css Colors 的定义,在顶部声明只能使用蓝色、红色和绿色。
编辑:好的,让我澄清一下。根据我的理解,这在本质上是不可能的。但是,您可以使用 Less 和 Sass 做一些事情来达到您想要的结果。 Here 是一些关于 Less Color 函数的教程。最有趣的是关于混合颜色的部分:
.box.mix {
background-color: mix(@blue, @yellow, 50%);
}
不过,我没有这方面的经验,您需要了解一下。
我想知道答案是否不只是 'mix' RGB 颜色?
var green = [15, 167, 73];
var blue = [0, 152, 215];
var orange = [243, 123, 38];
var gold = [255, 230, 101];
generateTrueColor(greenRatio, blueRatio, orangeRatio, goldRatio){
for(var i = 0; i < 3, i++){
RGB[i] = greenRatio * green[i] + blueRatio * blue[i] + orangeRatio * orange[i] + goldRatio * gold[i];
}
return RGB;
for(var i = 0; i < 3, i++){
if(RGB[i] > 255) RGB[i] = 255;
}
}
generateTrueColor(1, 0.1, 0.1, 0.1);
我不确定除以 50 是 right/best 的事情,但这很有效:
// Note that the results differ from "true" blue, green, orange, and gold; the colors used to represent these are custom versions of those colors, as found on the True Colors website
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Sandbox
{
public partial class FormTrueColorsMain : Form
{
// Primary constituents of the "True Colors" hues
const int GREEN_RED = 15;
const int GREEN_GREEN = 167;
const int GREEN_BLUE = 73;
const int BLUE_RED = 0;
const int BLUE_GREEN = 152;
const int BLUE_BLUE = 215;
const int ORANGE_RED = 243;
const int ORANGE_GREEN = 123;
const int ORANGE_BLUE = 38;
const int GOLD_RED = 255;
const int GOLD_GREEN = 230;
const int GOLD_BLUE = 101;
Color tcGreen = Color.FromArgb(15, 167, 73);
Color tcGreenComplement = Color.FromArgb(240, 88, 182);
Color tcBlue = Color.FromArgb(0, 152, 215);
Color tcOrange = Color.FromArgb(243, 123, 38);
Color tcGold = Color.FromArgb(255, 230, 101);
public FormTrueColorsMain()
{
InitializeComponent();
InitializeControls();
}
private void InitializeControls()
{
lblGreen.ForeColor = tcGreen;
lblGreen.BackColor = Color.White; // tcGreenComplement;
lblBlue.ForeColor = tcBlue;
lblBlue.BackColor = Color.White;
lblOrange.ForeColor = tcOrange;
lblOrange.BackColor = Color.Black;
lblGold.ForeColor = tcGold;
lblGold.BackColor = Color.Black;
// For these to work, needed to also comment out "Application.EnableVisualStyles();" in Program.cs (see Crispy's answer at
progressBarGreen.ForeColor = tcGreen;
progressBarGreen.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarBlue.ForeColor = tcBlue;
progressBarBlue.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarOrange.ForeColor = tcOrange;
progressBarOrange.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarGold.ForeColor = tcGold;
progressBarGold.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
}
private void button1_Click(object sender, EventArgs e)
{
// If they have already been set (user clicked the arrows rather than entered the value directly), this is moot but it's
// probably not worthwhile checking to see whether their value is 0, and only calling the methods conditionally in that case.
SetGreenProgressBar();
SetBlueProgressBar();
SetOrangeProgressBar();
SetGoldProgressBar();
int greenVal = (int)numericUpDownGreen.Value;
int blueVal = (int)numericUpDownBlue.Value;
int orangeVal = (int)numericUpDownOrange.Value;
int goldVal = (int)numericUpDownGold.Value;
Color trueColor = GetTrueCombinedColor(greenVal, blueVal, orangeVal, goldVal);
pictureBoxTCCombo.BackColor = trueColor;
}
private Color GetTrueCombinedColor(int greenVal, int blueVal, int orangeVal, int goldVal)
{
// tcBlue has no red, so can disregard blueVal for redTotal
int redTotal = ((greenVal * GREEN_RED) + (orangeVal * ORANGE_RED) + (goldVal * GOLD_RED));
int greenTotal = ((greenVal * GREEN_GREEN) + (blueVal * BLUE_GREEN) + (orangeVal * ORANGE_GREEN) + (goldVal * GOLD_GREEN));
int blueTotal = ((greenVal * GREEN_BLUE) + (blueVal * BLUE_BLUE) + (orangeVal * ORANGE_BLUE) + (goldVal * GOLD_BLUE));
int redWeight = redTotal / 50;
int greenWeight = greenTotal / 50;
int blueWeight = blueTotal / 50;
if (redWeight <= 0) redWeight = 1;
if (greenWeight <= 0) greenWeight = 1;
if (blueWeight <= 0) blueWeight = 1;
if (redWeight >= 256) redWeight = 255;
if (greenWeight >= 256) greenWeight = 255;
if (blueWeight >= 256) blueWeight = 255;
Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight);
//Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight, 10);
return trueColorCombo;
}
private void numericUpDownGreen_ValueChanged(object sender, EventArgs e)
{
SetGreenProgressBar();
}
private void SetGreenProgressBar()
{
progressBarGreen.Value = (int)numericUpDownGreen.Value;
}
private void numericUpDownBlue_ValueChanged(object sender, EventArgs e)
{
SetBlueProgressBar();
}
private void SetBlueProgressBar()
{
progressBarBlue.Value = (int)numericUpDownBlue.Value;
}
private void numericUpDownOrange_ValueChanged(object sender, EventArgs e)
{
SetOrangeProgressBar();
}
private void SetOrangeProgressBar()
{
progressBarOrange.Value = (int)numericUpDownOrange.Value;
}
private void numericUpDownGold_ValueChanged(object sender, EventArgs e)
{
SetGoldProgressBar();
}
private void SetGoldProgressBar()
{
progressBarGold.Value = (int)numericUpDownGold.Value;
}
}
}
实用程序如下所示:
辛迪·劳珀,尽情享受吧!
有多种混合颜色的方法,具体取决于您使用的颜色模型:
以下代码片段演示了两种混合方法。最左边的列显示四种原始颜色。下一列显示具有 0.25 不透明度的相同颜色,从而产生半透明颜色。第三列将半透明颜色叠加在一起,相当于 alpha 合成。
第四列显示了另一种混合方法。这里我们看到分别对四种原始颜色的R、G、B分量进行平均的结果。
var Colors = {
names: ['green', 'blue', 'orange', 'gold'],
values: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
};
Colors.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Colors.toColorString = function (value) {
var g = Colors,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(value.r), toHex2(value.g), toHex2(value.b) ];
return parts.join('');
};
Colors.load = function () {
var g = Colors,
names = g.names,
values = g.values,
containers = {
original: document.getElementById('original'),
translucent: document.getElementById('translucent'),
layered: document.getElementById('layered'),
averaged: document.getElementById('averaged')
},
averaged = { r: 0, g: 0, b: 0 };
document.body.style.paddingTop = 10*(1+names.length) + 'px';
for (var i = 0; i < names.length; ++i) {
var name = names[i],
value = values[name],
color = g.toColorString(value),
swatch = document.createElement('div'),
proportion = 1 / names.length;
swatch.className = 'swatch';
swatch.style.backgroundColor = color;
containers.original.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.opacity = proportion;
containers.translucent.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.height = 60 + 10*(names.length-1) + 'px';
swatch.style.top = 10*(1+i-names.length) + 'px';
containers.layered.appendChild(swatch);
averaged.r += proportion * value.r;
averaged.g += proportion * value.g;
averaged.b += proportion * value.b;
}
swatch = document.createElement('div');
swatch.className = 'swatch';
averaged.r = Math.round(averaged.r);
averaged.g = Math.round(averaged.g);
averaged.b = Math.round(averaged.b);
swatch.style.backgroundColor = g.toColorString(averaged);
containers.averaged.appendChild(swatch);
};
window.onload = Colors.load;
body {
font-family: sans-serif;
font-size: 24px;
margin: 0;
padding-left: 20px;
}
.display {
width: 120px;
float: left;
}
.swatch {
width: 100px;
height: 60px;
margin-bottom: 10px;
}
.layered {
position: relative;
height: 60px;
}
.layered .swatch {
position: absolute;
}
<div id="original" class="display"></div>
<div id="translucent" class="display"></div>
<div id="layered" class="display layered"></div>
<div id="averaged" class="display"></div>
在上面的演示中,我们让网络浏览器为我们进行 alpha 合成。我们也可以直接进行 alpha 合成。图层不透明度相当于alpha通道,所以我们将每种颜色的alpha通道设置为颜色的权重。也就是说,如果一个颜色的权重是25%,我们就把它的alpha通道设置为0.25。
请注意,alpha 通道的范围是从 0 到 1。但是,我们的 RGB 分量的范围是从 0 到 255。
假设我们混合这两种颜色:
- RGB 值
background
带 alpha 通道 alpha.background
- RGB 值
foreground
带 alpha 通道 alpha.foreground
我们计算结果颜色的 alpha 通道 alpha.mix
如下:
alpha.mix = 1 - (1-alpha.background)*(1-alpha.foreground);
要计算 RGB 值的 R 分量 mix
,我们这样做:
mix.r = 255 * (foreground.r/255.0 * alpha.foreground/alpha.mix +
mix.r/255.0 * alpha.background*(1-alpha.foreground)/alpha.mix);
同样对于 G 组件 mix.g
和 B 组件 mix.b
。
下面的代码片段是一个交互式演示,它将 alpha 合成与并行平均 RGB 分量的更简单方法进行了比较。 运行 代码并使用滑块来查看这两种方法之间的区别。
var Mixer = {
color: {
names: ['green', 'blue', 'orange', 'gold'],
rgb: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
},
style: {
swatch: { width: 150, height: 90, margin: { right: 15 } },
slider: { height: 20 },
handle: { width: 20, height: 34 }
}
};
Mixer.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Mixer.toCSS = function (rgb) {
var g = Mixer,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(rgb.r), toHex2(rgb.g), toHex2(rgb.b) ];
return parts.join('');
};
Mixer.toString = function (rgb) {
return 'rgb(' + [rgb.r, rgb.g, rgb.b].join(', ') + ')';
};
Mixer.makeUnselectable = function (element) {
element.className += ' unselectable';
element.ondragstart = element.onselectstart = function (event) {
event.preventDefault();
};
};
Mixer.makeElement = function (tag, className, innerHTML, unselectable) {
var g = Mixer,
element = document.createElement(tag);
element.className = (className ? className : '');
element.innerHTML = (innerHTML ? innerHTML : '');
if (unselectable) {
g.makeUnselectable(element);
}
return element;
};
Mixer.handleDown = function (event) {
event = event || window.event;
var g = Mixer;
g.mouseX = { depart: event.screenX };
g.activeHandle = this;
window.onmousemove = Mixer.handleMove;
window.onmouseup = Mixer.handleUp;
};
Mixer.handleMove = function (event) {
event = event || window.event;
var g = Mixer,
handle = g.activeHandle,
pos = handle.pos,
handles = g.handles,
num = g.num,
slider = g.slider,
proportion = g.proportion,
segments = g.segments,
handleWidth = g.style.handle.width,
swatches = g.swatches,
canvas = g.canvas,
context = g.context,
mixingFunctions = g.mixingFunctions,
limit = {
min: (pos == 0 ? 0 : handles[pos-1].right),
max: (pos == num-2 ? slider.length.total : handles[pos+1].left) -
handleWidth
},
mouseX = g.mouseX;
mouseX.current = event.screenX;
var left = handle.left + mouseX.current - mouseX.depart;
if (left < limit.min) {
left = limit.min;
}
if (left > limit.max) {
left = limit.max;
}
handle.newLeft = left;
segments[pos] = left - limit.min;
context.fillStyle = swatches[pos].css;
context.fillRect(limit.min, 0, segments[pos], canvas.height);
segments[pos+1] = limit.max - left;
context.fillStyle = swatches[pos+1].css;
context.fillRect(left + handleWidth, 0, segments[pos+1], canvas.height);
handle.style.left = left + 'px';
var segmentSpan = segments[pos] + segments[pos+1],
proportionSpan = proportion[pos] + proportion[pos+1];
if (segmentSpan != 0) {
proportion[pos] = Math.round(segments[pos]/segmentSpan * proportionSpan);
proportion[pos+1] = proportionSpan - proportion[pos];
swatches[pos].percent.innerHTML = proportion[pos] + '%';
swatches[pos+1].percent.innerHTML = proportion[pos+1] + '%';
}
g.mixColors();
};
Mixer.handleUp = function (event) {
var g = Mixer,
handle = g.activeHandle;
window.onmousemove = null;
window.onmouseup = null;
handle.left = handle.newLeft;
handle.right = handle.left + g.style.handle.width;
};
Mixer.makeFunctionName = function (title) {
var parts = ['mix'],
tokens = title.split(' ');
for (var i = 0; i < tokens.length; ++i) {
var token = tokens[i];
parts.push(token[0].toUpperCase() + token.substring(1));
}
return parts.join('');
};
Mixer.mixAlphaCompositing = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = {},
subs = ['r', 'g', 'b'];
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = swatches[0].rgb[x];
}
var alpha = { back: proportion[0]/100 };
for (var pos = 1; pos < num; ++pos) {
var fore = swatches[pos].rgb;
alpha.fore = proportion[pos]/100,
alpha.mix = 1 - (1-alpha.back)*(1-alpha.fore);
if (alpha.mix >= 1.0e-6) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = 255 * (fore[x]/255 * alpha.fore/alpha.mix +
mix[x]/255 * alpha.back*(1-alpha.fore)/alpha.mix);
}
}
alpha.back = alpha.mix;
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
swatch.style.opacity = alpha.mix;
};
};
Mixer.mixWeightedAverage = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = { r: 0, g: 0, b: 0 },
subs = ['r', 'g', 'b'];
for (var pos = 0; pos < num; ++pos) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] += proportion[pos]/100 * swatches[pos].rgb[x];
}
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
};
};
Mixer.mixColors = function () {
var g = Mixer,
mixingFunctions = g.mixingFunctions;
for (var i = 0; i < mixingFunctions.length; ++i) {
mixingFunctions[i]();
}
};
Mixer.load = function () {
var g = Mixer,
style = g.style;
// Make color swatches.
var palette = g.palette = document.getElementById('palette'),
names = g.color.names,
swatches = g.swatches = [],
num = g.num = names.length;
for (var i = 0; i < num; ++i) {
var name = names[i],
rgb = g.color.rgb[name],
css = g.toCSS(rgb),
container = g.makeElement('div', 'swatchContainer', '', true),
percent = g.makeElement('div', 'title', '', true),
swatch = g.makeElement('div', 'swatch', '', true);
swatches[i] = { rgb: rgb, css: css, percent: percent };
container.appendChild(percent);
swatch.style.backgroundColor = css;
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
swatch.style.marginRight = style.swatch.margin.right + 'px';
container.appendChild(swatch);
container.appendChild(g.makeElement('div', 'label', g.toString(rgb), true));
container.appendChild(g.makeElement('div', 'label', css, true));
palette.appendChild(container);
}
var totalWidth = num*style.swatch.width + (num-1)*style.swatch.margin.right;
// Initialize proportions.
var proportion = g.proportion = new Array(num),
each = Math.floor(100/num);
for (var i = 0; i < num-1; ++i) {
proportion[i] = each;
}
proportion[num-1] = 100 - (num-1)*each;
for (var i = 0; i < num; ++i) {
swatches[i].percent.innerHTML = proportion[i] + '%';
}
// Prepare the blended swatches.
var blend = g.blend = { container: document.getElementById('blend') },
mixers = ['alpha compositing', 'weighted average'],
between = (totalWidth - mixers.length*style.swatch.width) /
(mixers.length + 1);
g.makeUnselectable(blend);
blend.container.style.width = totalWidth + 'px';
blend.container.style.height = style.swatch.height + 'px';
g.mixingFunctions = [];
for (var i = 0; i < mixers.length; ++i) {
var mixer = mixers[i],
container = g.makeElement('div', 'swatchContainer', '', true),
title = g.makeElement('div', 'title', mixer, true),
swatch = g.makeElement('div', 'swatch', '', true),
label = {
rgb: g.makeElement('div', 'label', '', true),
css: g.makeElement('div', 'label', '', true)
};
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
container.style.left = i*style.swatch.width + (i+1)*between + 'px';
container.appendChild(title);
container.appendChild(swatch);
container.appendChild(label.rgb);
container.appendChild(label.css);
blend.container.appendChild(container);
var functionName = g.makeFunctionName(mixer),
mixingFunction = g[functionName](swatch, label);
g.mixingFunctions.push(mixingFunction);
}
// Assemble the slider widget.
var slider = g.slider = document.getElementById('slider');
slider.length = {
total: totalWidth,
free: totalWidth - (num-1)*style.handle.width
};
var segments = g.segments = new Array(num);
var tail = slider.length.free;
for (var i = 0; i < num-1; ++i) {
var current = Math.round(proportion[i]/100*slider.length.free);
segments[i] = current;
tail -= current;
}
segments[num-1] = tail;
slider.style.width = slider.length.total + 'px';
slider.style.height = style.slider.height + 'px';
var canvas = g.canvas = g.makeElement('canvas'),
context = g.context = canvas.getContext('2d');
g.makeUnselectable(slider);
g.makeUnselectable(canvas);
canvas.width = slider.length.total;
canvas.height = style.slider.height;
slider.appendChild(canvas);
var handles = g.handles = new Array(num-1);
var left = 0;
for (var i = 0; i < num; ++i) {
context.fillStyle = swatches[i].css;
context.fillRect(left, 0, segments[i], canvas.height);
if (i == num-1) {
break;
}
var handle = handles[i] = g.makeElement('div', 'handle', '', true);
handle.pos = i;
handle.style.width = style.handle.width + 'px';
handle.style.height = style.handle.height + 'px';
handle.style.top = (style.slider.height - style.handle.height)/2 + 'px';
handle.left = left + segments[i];
handle.style.left = handle.left + 'px';
handle.right = handle.left + style.handle.width;
left = handle.right;
handle.onmousedown = g.handleDown;
slider.appendChild(handle);
}
g.mixColors();
};
window.onload = Mixer.load;
body {
font-family: sans-serif;
color: #444;
}
.unselectable {
-webkit-user-select: none;
-khtml-user-drag: none;
-khtml-user-select: none;
-moz-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
}
#blend {
position: relative;
padding: 10px 0 90px;
}
#blend .swatchContainer {
position: absolute;
}
#blend .swatchContainer .title {
font-size: 17px;
padding-bottom: 5px;
}
#slider {
margin: 20px 0;
position: relative;
}
.handle {
position: absolute;
background: #444;
border-radius: 5px;
cursor: pointer;
}
.swatchContainer {
float: left;
}
.swatchContainer .title {
font-size: 25px;
text-align: center;
}
.swatchContainer .label {
font-size: 17px;
}
<div id="blend"></div>
<div id="slider"></div>
<div id="palette"></div>
如果知道红色、绿色和蓝色的 "weights",就可以使用 class 来创建一种颜色,比如
.blaRGB {
color: rgb(128, 128, 128)
}
.blaHSL {
color: hsl(33%, 34%, 33%)
}
并像这样在 HTML 中使用它:
<p class="blaRGB">BLA RGB</p>
<p class="blaHSL">BLA HSL</p>
根据上面显示的值,blaRGB
是暗灰色,blaHSL
是白色。
但是如果要表示其他颜色的组合,例如绿色、蓝色、橙色和金色,该怎么办?
有没有一种方法可以使用如下所示的符号来定义此类颜色?
.CyndiLauper {
color: truecolors(24, 13, 11, 12)
}
或者用 color: gbog(24, 13, 11, 12)
其中 gbog
中的字母分别代表绿色、蓝色、橙色和金色?
目的是根据上面的 CSS 定义,HTML
<p class="CyndiLauper">These are your True Colors, shining through!</p>
将以这四种颜色的加权组合显示文本。
我相信使用绿色、蓝色、橙色和金色的 RGB 值进行一些复杂的数学运算是可能的,但我不知道如何进行。
更新
我意识到我最初忽略的问题的关键组成部分是 "What exactly do you mean by green, blue, orange, and gold"?
为了回答这个问题,根据官方 "True Colors" website,并使用 ColorZilla 浏览器插件,这些颜色的 RGB 值为:
green = 15, 167, 73
blue = 0, 152, 215
orange = 243, 123, 38
gold = 255, 230, 101
(在我看来,它们实际上更像是森林绿、道奇蓝、红橙色和黄色。)
不,你不能。这是一个 link 到 W3 Css Colors 的定义,在顶部声明只能使用蓝色、红色和绿色。
编辑:好的,让我澄清一下。根据我的理解,这在本质上是不可能的。但是,您可以使用 Less 和 Sass 做一些事情来达到您想要的结果。 Here 是一些关于 Less Color 函数的教程。最有趣的是关于混合颜色的部分:
.box.mix {
background-color: mix(@blue, @yellow, 50%);
}
不过,我没有这方面的经验,您需要了解一下。
我想知道答案是否不只是 'mix' RGB 颜色?
var green = [15, 167, 73];
var blue = [0, 152, 215];
var orange = [243, 123, 38];
var gold = [255, 230, 101];
generateTrueColor(greenRatio, blueRatio, orangeRatio, goldRatio){
for(var i = 0; i < 3, i++){
RGB[i] = greenRatio * green[i] + blueRatio * blue[i] + orangeRatio * orange[i] + goldRatio * gold[i];
}
return RGB;
for(var i = 0; i < 3, i++){
if(RGB[i] > 255) RGB[i] = 255;
}
}
generateTrueColor(1, 0.1, 0.1, 0.1);
我不确定除以 50 是 right/best 的事情,但这很有效:
// Note that the results differ from "true" blue, green, orange, and gold; the colors used to represent these are custom versions of those colors, as found on the True Colors website
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Sandbox
{
public partial class FormTrueColorsMain : Form
{
// Primary constituents of the "True Colors" hues
const int GREEN_RED = 15;
const int GREEN_GREEN = 167;
const int GREEN_BLUE = 73;
const int BLUE_RED = 0;
const int BLUE_GREEN = 152;
const int BLUE_BLUE = 215;
const int ORANGE_RED = 243;
const int ORANGE_GREEN = 123;
const int ORANGE_BLUE = 38;
const int GOLD_RED = 255;
const int GOLD_GREEN = 230;
const int GOLD_BLUE = 101;
Color tcGreen = Color.FromArgb(15, 167, 73);
Color tcGreenComplement = Color.FromArgb(240, 88, 182);
Color tcBlue = Color.FromArgb(0, 152, 215);
Color tcOrange = Color.FromArgb(243, 123, 38);
Color tcGold = Color.FromArgb(255, 230, 101);
public FormTrueColorsMain()
{
InitializeComponent();
InitializeControls();
}
private void InitializeControls()
{
lblGreen.ForeColor = tcGreen;
lblGreen.BackColor = Color.White; // tcGreenComplement;
lblBlue.ForeColor = tcBlue;
lblBlue.BackColor = Color.White;
lblOrange.ForeColor = tcOrange;
lblOrange.BackColor = Color.Black;
lblGold.ForeColor = tcGold;
lblGold.BackColor = Color.Black;
// For these to work, needed to also comment out "Application.EnableVisualStyles();" in Program.cs (see Crispy's answer at
progressBarGreen.ForeColor = tcGreen;
progressBarGreen.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarBlue.ForeColor = tcBlue;
progressBarBlue.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarOrange.ForeColor = tcOrange;
progressBarOrange.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarGold.ForeColor = tcGold;
progressBarGold.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
}
private void button1_Click(object sender, EventArgs e)
{
// If they have already been set (user clicked the arrows rather than entered the value directly), this is moot but it's
// probably not worthwhile checking to see whether their value is 0, and only calling the methods conditionally in that case.
SetGreenProgressBar();
SetBlueProgressBar();
SetOrangeProgressBar();
SetGoldProgressBar();
int greenVal = (int)numericUpDownGreen.Value;
int blueVal = (int)numericUpDownBlue.Value;
int orangeVal = (int)numericUpDownOrange.Value;
int goldVal = (int)numericUpDownGold.Value;
Color trueColor = GetTrueCombinedColor(greenVal, blueVal, orangeVal, goldVal);
pictureBoxTCCombo.BackColor = trueColor;
}
private Color GetTrueCombinedColor(int greenVal, int blueVal, int orangeVal, int goldVal)
{
// tcBlue has no red, so can disregard blueVal for redTotal
int redTotal = ((greenVal * GREEN_RED) + (orangeVal * ORANGE_RED) + (goldVal * GOLD_RED));
int greenTotal = ((greenVal * GREEN_GREEN) + (blueVal * BLUE_GREEN) + (orangeVal * ORANGE_GREEN) + (goldVal * GOLD_GREEN));
int blueTotal = ((greenVal * GREEN_BLUE) + (blueVal * BLUE_BLUE) + (orangeVal * ORANGE_BLUE) + (goldVal * GOLD_BLUE));
int redWeight = redTotal / 50;
int greenWeight = greenTotal / 50;
int blueWeight = blueTotal / 50;
if (redWeight <= 0) redWeight = 1;
if (greenWeight <= 0) greenWeight = 1;
if (blueWeight <= 0) blueWeight = 1;
if (redWeight >= 256) redWeight = 255;
if (greenWeight >= 256) greenWeight = 255;
if (blueWeight >= 256) blueWeight = 255;
Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight);
//Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight, 10);
return trueColorCombo;
}
private void numericUpDownGreen_ValueChanged(object sender, EventArgs e)
{
SetGreenProgressBar();
}
private void SetGreenProgressBar()
{
progressBarGreen.Value = (int)numericUpDownGreen.Value;
}
private void numericUpDownBlue_ValueChanged(object sender, EventArgs e)
{
SetBlueProgressBar();
}
private void SetBlueProgressBar()
{
progressBarBlue.Value = (int)numericUpDownBlue.Value;
}
private void numericUpDownOrange_ValueChanged(object sender, EventArgs e)
{
SetOrangeProgressBar();
}
private void SetOrangeProgressBar()
{
progressBarOrange.Value = (int)numericUpDownOrange.Value;
}
private void numericUpDownGold_ValueChanged(object sender, EventArgs e)
{
SetGoldProgressBar();
}
private void SetGoldProgressBar()
{
progressBarGold.Value = (int)numericUpDownGold.Value;
}
}
}
实用程序如下所示:
辛迪·劳珀,尽情享受吧!
有多种混合颜色的方法,具体取决于您使用的颜色模型:
以下代码片段演示了两种混合方法。最左边的列显示四种原始颜色。下一列显示具有 0.25 不透明度的相同颜色,从而产生半透明颜色。第三列将半透明颜色叠加在一起,相当于 alpha 合成。
第四列显示了另一种混合方法。这里我们看到分别对四种原始颜色的R、G、B分量进行平均的结果。
var Colors = {
names: ['green', 'blue', 'orange', 'gold'],
values: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
};
Colors.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Colors.toColorString = function (value) {
var g = Colors,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(value.r), toHex2(value.g), toHex2(value.b) ];
return parts.join('');
};
Colors.load = function () {
var g = Colors,
names = g.names,
values = g.values,
containers = {
original: document.getElementById('original'),
translucent: document.getElementById('translucent'),
layered: document.getElementById('layered'),
averaged: document.getElementById('averaged')
},
averaged = { r: 0, g: 0, b: 0 };
document.body.style.paddingTop = 10*(1+names.length) + 'px';
for (var i = 0; i < names.length; ++i) {
var name = names[i],
value = values[name],
color = g.toColorString(value),
swatch = document.createElement('div'),
proportion = 1 / names.length;
swatch.className = 'swatch';
swatch.style.backgroundColor = color;
containers.original.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.opacity = proportion;
containers.translucent.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.height = 60 + 10*(names.length-1) + 'px';
swatch.style.top = 10*(1+i-names.length) + 'px';
containers.layered.appendChild(swatch);
averaged.r += proportion * value.r;
averaged.g += proportion * value.g;
averaged.b += proportion * value.b;
}
swatch = document.createElement('div');
swatch.className = 'swatch';
averaged.r = Math.round(averaged.r);
averaged.g = Math.round(averaged.g);
averaged.b = Math.round(averaged.b);
swatch.style.backgroundColor = g.toColorString(averaged);
containers.averaged.appendChild(swatch);
};
window.onload = Colors.load;
body {
font-family: sans-serif;
font-size: 24px;
margin: 0;
padding-left: 20px;
}
.display {
width: 120px;
float: left;
}
.swatch {
width: 100px;
height: 60px;
margin-bottom: 10px;
}
.layered {
position: relative;
height: 60px;
}
.layered .swatch {
position: absolute;
}
<div id="original" class="display"></div>
<div id="translucent" class="display"></div>
<div id="layered" class="display layered"></div>
<div id="averaged" class="display"></div>
在上面的演示中,我们让网络浏览器为我们进行 alpha 合成。我们也可以直接进行 alpha 合成。图层不透明度相当于alpha通道,所以我们将每种颜色的alpha通道设置为颜色的权重。也就是说,如果一个颜色的权重是25%,我们就把它的alpha通道设置为0.25。
请注意,alpha 通道的范围是从 0 到 1。但是,我们的 RGB 分量的范围是从 0 到 255。
假设我们混合这两种颜色:
- RGB 值
background
带 alpha 通道alpha.background
- RGB 值
foreground
带 alpha 通道alpha.foreground
我们计算结果颜色的 alpha 通道 alpha.mix
如下:
alpha.mix = 1 - (1-alpha.background)*(1-alpha.foreground);
要计算 RGB 值的 R 分量 mix
,我们这样做:
mix.r = 255 * (foreground.r/255.0 * alpha.foreground/alpha.mix +
mix.r/255.0 * alpha.background*(1-alpha.foreground)/alpha.mix);
同样对于 G 组件 mix.g
和 B 组件 mix.b
。
下面的代码片段是一个交互式演示,它将 alpha 合成与并行平均 RGB 分量的更简单方法进行了比较。 运行 代码并使用滑块来查看这两种方法之间的区别。
var Mixer = {
color: {
names: ['green', 'blue', 'orange', 'gold'],
rgb: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
},
style: {
swatch: { width: 150, height: 90, margin: { right: 15 } },
slider: { height: 20 },
handle: { width: 20, height: 34 }
}
};
Mixer.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Mixer.toCSS = function (rgb) {
var g = Mixer,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(rgb.r), toHex2(rgb.g), toHex2(rgb.b) ];
return parts.join('');
};
Mixer.toString = function (rgb) {
return 'rgb(' + [rgb.r, rgb.g, rgb.b].join(', ') + ')';
};
Mixer.makeUnselectable = function (element) {
element.className += ' unselectable';
element.ondragstart = element.onselectstart = function (event) {
event.preventDefault();
};
};
Mixer.makeElement = function (tag, className, innerHTML, unselectable) {
var g = Mixer,
element = document.createElement(tag);
element.className = (className ? className : '');
element.innerHTML = (innerHTML ? innerHTML : '');
if (unselectable) {
g.makeUnselectable(element);
}
return element;
};
Mixer.handleDown = function (event) {
event = event || window.event;
var g = Mixer;
g.mouseX = { depart: event.screenX };
g.activeHandle = this;
window.onmousemove = Mixer.handleMove;
window.onmouseup = Mixer.handleUp;
};
Mixer.handleMove = function (event) {
event = event || window.event;
var g = Mixer,
handle = g.activeHandle,
pos = handle.pos,
handles = g.handles,
num = g.num,
slider = g.slider,
proportion = g.proportion,
segments = g.segments,
handleWidth = g.style.handle.width,
swatches = g.swatches,
canvas = g.canvas,
context = g.context,
mixingFunctions = g.mixingFunctions,
limit = {
min: (pos == 0 ? 0 : handles[pos-1].right),
max: (pos == num-2 ? slider.length.total : handles[pos+1].left) -
handleWidth
},
mouseX = g.mouseX;
mouseX.current = event.screenX;
var left = handle.left + mouseX.current - mouseX.depart;
if (left < limit.min) {
left = limit.min;
}
if (left > limit.max) {
left = limit.max;
}
handle.newLeft = left;
segments[pos] = left - limit.min;
context.fillStyle = swatches[pos].css;
context.fillRect(limit.min, 0, segments[pos], canvas.height);
segments[pos+1] = limit.max - left;
context.fillStyle = swatches[pos+1].css;
context.fillRect(left + handleWidth, 0, segments[pos+1], canvas.height);
handle.style.left = left + 'px';
var segmentSpan = segments[pos] + segments[pos+1],
proportionSpan = proportion[pos] + proportion[pos+1];
if (segmentSpan != 0) {
proportion[pos] = Math.round(segments[pos]/segmentSpan * proportionSpan);
proportion[pos+1] = proportionSpan - proportion[pos];
swatches[pos].percent.innerHTML = proportion[pos] + '%';
swatches[pos+1].percent.innerHTML = proportion[pos+1] + '%';
}
g.mixColors();
};
Mixer.handleUp = function (event) {
var g = Mixer,
handle = g.activeHandle;
window.onmousemove = null;
window.onmouseup = null;
handle.left = handle.newLeft;
handle.right = handle.left + g.style.handle.width;
};
Mixer.makeFunctionName = function (title) {
var parts = ['mix'],
tokens = title.split(' ');
for (var i = 0; i < tokens.length; ++i) {
var token = tokens[i];
parts.push(token[0].toUpperCase() + token.substring(1));
}
return parts.join('');
};
Mixer.mixAlphaCompositing = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = {},
subs = ['r', 'g', 'b'];
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = swatches[0].rgb[x];
}
var alpha = { back: proportion[0]/100 };
for (var pos = 1; pos < num; ++pos) {
var fore = swatches[pos].rgb;
alpha.fore = proportion[pos]/100,
alpha.mix = 1 - (1-alpha.back)*(1-alpha.fore);
if (alpha.mix >= 1.0e-6) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = 255 * (fore[x]/255 * alpha.fore/alpha.mix +
mix[x]/255 * alpha.back*(1-alpha.fore)/alpha.mix);
}
}
alpha.back = alpha.mix;
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
swatch.style.opacity = alpha.mix;
};
};
Mixer.mixWeightedAverage = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = { r: 0, g: 0, b: 0 },
subs = ['r', 'g', 'b'];
for (var pos = 0; pos < num; ++pos) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] += proportion[pos]/100 * swatches[pos].rgb[x];
}
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
};
};
Mixer.mixColors = function () {
var g = Mixer,
mixingFunctions = g.mixingFunctions;
for (var i = 0; i < mixingFunctions.length; ++i) {
mixingFunctions[i]();
}
};
Mixer.load = function () {
var g = Mixer,
style = g.style;
// Make color swatches.
var palette = g.palette = document.getElementById('palette'),
names = g.color.names,
swatches = g.swatches = [],
num = g.num = names.length;
for (var i = 0; i < num; ++i) {
var name = names[i],
rgb = g.color.rgb[name],
css = g.toCSS(rgb),
container = g.makeElement('div', 'swatchContainer', '', true),
percent = g.makeElement('div', 'title', '', true),
swatch = g.makeElement('div', 'swatch', '', true);
swatches[i] = { rgb: rgb, css: css, percent: percent };
container.appendChild(percent);
swatch.style.backgroundColor = css;
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
swatch.style.marginRight = style.swatch.margin.right + 'px';
container.appendChild(swatch);
container.appendChild(g.makeElement('div', 'label', g.toString(rgb), true));
container.appendChild(g.makeElement('div', 'label', css, true));
palette.appendChild(container);
}
var totalWidth = num*style.swatch.width + (num-1)*style.swatch.margin.right;
// Initialize proportions.
var proportion = g.proportion = new Array(num),
each = Math.floor(100/num);
for (var i = 0; i < num-1; ++i) {
proportion[i] = each;
}
proportion[num-1] = 100 - (num-1)*each;
for (var i = 0; i < num; ++i) {
swatches[i].percent.innerHTML = proportion[i] + '%';
}
// Prepare the blended swatches.
var blend = g.blend = { container: document.getElementById('blend') },
mixers = ['alpha compositing', 'weighted average'],
between = (totalWidth - mixers.length*style.swatch.width) /
(mixers.length + 1);
g.makeUnselectable(blend);
blend.container.style.width = totalWidth + 'px';
blend.container.style.height = style.swatch.height + 'px';
g.mixingFunctions = [];
for (var i = 0; i < mixers.length; ++i) {
var mixer = mixers[i],
container = g.makeElement('div', 'swatchContainer', '', true),
title = g.makeElement('div', 'title', mixer, true),
swatch = g.makeElement('div', 'swatch', '', true),
label = {
rgb: g.makeElement('div', 'label', '', true),
css: g.makeElement('div', 'label', '', true)
};
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
container.style.left = i*style.swatch.width + (i+1)*between + 'px';
container.appendChild(title);
container.appendChild(swatch);
container.appendChild(label.rgb);
container.appendChild(label.css);
blend.container.appendChild(container);
var functionName = g.makeFunctionName(mixer),
mixingFunction = g[functionName](swatch, label);
g.mixingFunctions.push(mixingFunction);
}
// Assemble the slider widget.
var slider = g.slider = document.getElementById('slider');
slider.length = {
total: totalWidth,
free: totalWidth - (num-1)*style.handle.width
};
var segments = g.segments = new Array(num);
var tail = slider.length.free;
for (var i = 0; i < num-1; ++i) {
var current = Math.round(proportion[i]/100*slider.length.free);
segments[i] = current;
tail -= current;
}
segments[num-1] = tail;
slider.style.width = slider.length.total + 'px';
slider.style.height = style.slider.height + 'px';
var canvas = g.canvas = g.makeElement('canvas'),
context = g.context = canvas.getContext('2d');
g.makeUnselectable(slider);
g.makeUnselectable(canvas);
canvas.width = slider.length.total;
canvas.height = style.slider.height;
slider.appendChild(canvas);
var handles = g.handles = new Array(num-1);
var left = 0;
for (var i = 0; i < num; ++i) {
context.fillStyle = swatches[i].css;
context.fillRect(left, 0, segments[i], canvas.height);
if (i == num-1) {
break;
}
var handle = handles[i] = g.makeElement('div', 'handle', '', true);
handle.pos = i;
handle.style.width = style.handle.width + 'px';
handle.style.height = style.handle.height + 'px';
handle.style.top = (style.slider.height - style.handle.height)/2 + 'px';
handle.left = left + segments[i];
handle.style.left = handle.left + 'px';
handle.right = handle.left + style.handle.width;
left = handle.right;
handle.onmousedown = g.handleDown;
slider.appendChild(handle);
}
g.mixColors();
};
window.onload = Mixer.load;
body {
font-family: sans-serif;
color: #444;
}
.unselectable {
-webkit-user-select: none;
-khtml-user-drag: none;
-khtml-user-select: none;
-moz-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
}
#blend {
position: relative;
padding: 10px 0 90px;
}
#blend .swatchContainer {
position: absolute;
}
#blend .swatchContainer .title {
font-size: 17px;
padding-bottom: 5px;
}
#slider {
margin: 20px 0;
position: relative;
}
.handle {
position: absolute;
background: #444;
border-radius: 5px;
cursor: pointer;
}
.swatchContainer {
float: left;
}
.swatchContainer .title {
font-size: 25px;
text-align: center;
}
.swatchContainer .label {
font-size: 17px;
}
<div id="blend"></div>
<div id="slider"></div>
<div id="palette"></div>