我正在寻找一种简单的算法来生成大量随机的、美观的颜色。所以没有疯狂的霓虹灯颜色,让人联想到粪便的颜色等等。
我已经找到了这个问题的解决方案,但它们依赖于替代调色板而不是RGB。 我宁愿直接使用RGB,而不是来回映射。这些其他解决方案也最多只能生成32种左右令人愉悦的随机颜色。
任何想法都很好。
我正在寻找一种简单的算法来生成大量随机的、美观的颜色。所以没有疯狂的霓虹灯颜色,让人联想到粪便的颜色等等。
我已经找到了这个问题的解决方案,但它们依赖于替代调色板而不是RGB。 我宁愿直接使用RGB,而不是来回映射。这些其他解决方案也最多只能生成32种左右令人愉悦的随机颜色。
任何想法都很好。
当前回答
这是我为我做的一个网站写的东西。它会自动为任何带有.flat-color-gen类的div生成随机的平面背景色。Jquery仅用于向页面添加css;它的主要部分是generateFlatColorWithOrder()方法,而不是必需的。
JsFiddle Link
(function($) {
function generateFlatColorWithOrder(num, rr, rg, rb) {
var colorBase = 256;
var red = 0;
var green = 0;
var blue = 0;
num = Math.round(num);
num = num + 1;
if (num != null) {
red = (num*rr) % 256;
green = (num*rg) % 256;
blue = (num*rb) % 256;
}
var redString = Math.round((red + colorBase) / 2).toString();
var greenString = Math.round((green + colorBase) / 2).toString();
var blueString = Math.round((blue + colorBase) / 2).toString();
return "rgb("+redString+", "+greenString+", "+blueString+")";
//return '#' + redString + greenString + blueString;
}
function generateRandomFlatColor() {
return generateFlatColorWithOrder(Math.round(Math.random()*127));
}
var rr = Math.round(Math.random()*1000);
var rg = Math.round(Math.random()*1000);
var rb = Math.round(Math.random()*1000);
console.log("random red: "+ rr);
console.log("random green: "+ rg);
console.log("random blue: "+ rb);
console.log("----------------------------------------------------");
$('.flat-color-gen').each(function(i, obj) {
console.log(generateFlatColorWithOrder(i));
$(this).css("background-color",generateFlatColorWithOrder(i, rr, rg, rb).toString());
});
})(window.jQuery);
其他回答
一个不应该被忽视的答案,因为它简单而有优势,就是对现实生活中的照片和绘画进行采样。在现代艺术图片、塞尚、梵高、莫内、照片的缩略图上随机选取你想要的任意数量的像素。这样做的好处是,您可以根据主题获取颜色,而且它们是有机颜色。只要把20 - 30张照片在一个文件夹和随机抽样随机PIC每次。
转换到HSV值是一种广泛的代码算法心理基于调色板。HSV更容易随机化。
这是我为我做的一个网站写的东西。它会自动为任何带有.flat-color-gen类的div生成随机的平面背景色。Jquery仅用于向页面添加css;它的主要部分是generateFlatColorWithOrder()方法,而不是必需的。
JsFiddle Link
(function($) {
function generateFlatColorWithOrder(num, rr, rg, rb) {
var colorBase = 256;
var red = 0;
var green = 0;
var blue = 0;
num = Math.round(num);
num = num + 1;
if (num != null) {
red = (num*rr) % 256;
green = (num*rg) % 256;
blue = (num*rb) % 256;
}
var redString = Math.round((red + colorBase) / 2).toString();
var greenString = Math.round((green + colorBase) / 2).toString();
var blueString = Math.round((blue + colorBase) / 2).toString();
return "rgb("+redString+", "+greenString+", "+blueString+")";
//return '#' + redString + greenString + blueString;
}
function generateRandomFlatColor() {
return generateFlatColorWithOrder(Math.round(Math.random()*127));
}
var rr = Math.round(Math.random()*1000);
var rg = Math.round(Math.random()*1000);
var rb = Math.round(Math.random()*1000);
console.log("random red: "+ rr);
console.log("random green: "+ rg);
console.log("random blue: "+ rb);
console.log("----------------------------------------------------");
$('.flat-color-gen').each(function(i, obj) {
console.log(generateFlatColorWithOrder(i));
$(this).css("background-color",generateFlatColorWithOrder(i, rr, rg, rb).toString());
});
})(window.jQuery);
你可以让它们在一定的亮度范围内。这样可以稍微控制“霓虹灯”颜色的数量。例如,如果“亮度”
brightness = sqrt(R^2+G^2+B^2)
在一定的高度范围内,它就会被洗掉,变成浅色。相反,如果它在某个下限内,它就会更暗。这将消除任何疯狂的、突出的颜色,如果你选择一个非常高或非常低的边界,它们都将非常接近白色或黑色。
下面是c#中的一个快速而肮脏的颜色生成器(使用本文中描述的“RYB方法”)。这是JavaScript重写的。
Use:
List<Color> ColorPalette = ColorGenerator.Generate(30).ToList();
前两种颜色往往是白色和暗色的黑色。我经常这样跳过它们(使用Linq):
List<Color> ColorsPalette = ColorGenerator
.Generate(30)
.Skip(2) // skip white and black
.ToList();
实现:
public static class ColorGenerator
{
// RYB color space
private static class RYB
{
private static readonly double[] White = { 1, 1, 1 };
private static readonly double[] Red = { 1, 0, 0 };
private static readonly double[] Yellow = { 1, 1, 0 };
private static readonly double[] Blue = { 0.163, 0.373, 0.6 };
private static readonly double[] Violet = { 0.5, 0, 0.5 };
private static readonly double[] Green = { 0, 0.66, 0.2 };
private static readonly double[] Orange = { 1, 0.5, 0 };
private static readonly double[] Black = { 0.2, 0.094, 0.0 };
public static double[] ToRgb(double r, double y, double b)
{
var rgb = new double[3];
for (int i = 0; i < 3; i++)
{
rgb[i] = White[i] * (1.0 - r) * (1.0 - b) * (1.0 - y) +
Red[i] * r * (1.0 - b) * (1.0 - y) +
Blue[i] * (1.0 - r) * b * (1.0 - y) +
Violet[i] * r * b * (1.0 - y) +
Yellow[i] * (1.0 - r) * (1.0 - b) * y +
Orange[i] * r * (1.0 - b) * y +
Green[i] * (1.0 - r) * b * y +
Black[i] * r * b * y;
}
return rgb;
}
}
private class Points : IEnumerable<double[]>
{
private readonly int pointsCount;
private double[] picked;
private int pickedCount;
private readonly List<double[]> points = new List<double[]>();
public Points(int count)
{
pointsCount = count;
}
private void Generate()
{
points.Clear();
var numBase = (int)Math.Ceiling(Math.Pow(pointsCount, 1.0 / 3.0));
var ceil = (int)Math.Pow(numBase, 3.0);
for (int i = 0; i < ceil; i++)
{
points.Add(new[]
{
Math.Floor(i/(double)(numBase*numBase))/ (numBase - 1.0),
Math.Floor((i/(double)numBase) % numBase)/ (numBase - 1.0),
Math.Floor((double)(i % numBase))/ (numBase - 1.0),
});
}
}
private double Distance(double[] p1)
{
double distance = 0;
for (int i = 0; i < 3; i++)
{
distance += Math.Pow(p1[i] - picked[i], 2.0);
}
return distance;
}
private double[] Pick()
{
if (picked == null)
{
picked = points[0];
points.RemoveAt(0);
pickedCount = 1;
return picked;
}
var d1 = Distance(points[0]);
int i1 = 0, i2 = 0;
foreach (var point in points)
{
var d2 = Distance(point);
if (d1 < d2)
{
i1 = i2;
d1 = d2;
}
i2 += 1;
}
var pick = points[i1];
points.RemoveAt(i1);
for (int i = 0; i < 3; i++)
{
picked[i] = (pickedCount * picked[i] + pick[i]) / (pickedCount + 1.0);
}
pickedCount += 1;
return pick;
}
public IEnumerator<double[]> GetEnumerator()
{
Generate();
for (int i = 0; i < pointsCount; i++)
{
yield return Pick();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public static IEnumerable<Color> Generate(int numOfColors)
{
var points = new Points(numOfColors);
foreach (var point in points)
{
var rgb = RYB.ToRgb(point[0], point[1], point[2]);
yield return Color.FromArgb(
(int)Math.Floor(255 * rgb[0]),
(int)Math.Floor(255 * rgb[1]),
(int)Math.Floor(255 * rgb[2]));
}
}
}
从算法上很难得到你想要的东西——人们研究颜色理论已经很长时间了,他们甚至不知道所有的规则。
然而,有一些规则可以用来剔除糟糕的颜色组合(例如,有冲突的颜色和选择互补的颜色的规则)。
我建议你去图书馆的艺术区看看关于色彩理论的书籍,在你尝试一个好颜色之前更好地理解什么是好颜色——看起来你甚至不知道为什么某些组合有效,而另一些则不行。
亚当