我有以下数据:
my %col1 = ( 'foo' => 1,
'bar' => 1 );
my %col2 = ('foo' => ['cat1','cat1','cat2'],
'bar' => ['cat3','cat2','cat3'] );
my %col3 = ('foo' => [2.3,1.2,1.0],
'bar' => [7.4,4.3,2.2]);
我要做的是创建一个如下所示的html表
但是在第四列,它包含了渐变色的形状。
颜色的强度由
col3
中的分数给出。形状可能只是一个简单的项目符号(•html:
•
)foo cat1,cat1,cat2 2.3,1.2,1
bar cat3,cat2,cat3 7.4,4.3,2.2
下图说明了我打算做什么:
每种颜色类别(第3列)的强度范围为1-10。
最好的办法是什么?
我遇到的关键问题不是创建html表,我可以做到这一点。
但更多的是如何创建一个基于HTML的渐变色形状。
我被以下代码困住了:
foreach my $nm (keys %col1) {
my @cats = @{$col2{$nm}};
my @vals = @{$col3{$nm}};
print $nm, " ", join(",",@cats), " " ,join(",",@vals), "\n";
}
最佳答案
如果我正确地理解了你的问题,你不会真的想要一个颜色渐变的形状。真正需要的是纯色对象,其颜色由两个参数决定:
类别(示例中的cat1、cat2和cat3)
着色程度(第3栏中的重量)
此外,示例中的颜色似乎遵循这样一种模型:较小的数字更接近白色,较大的数字更接近黑色,中间的数字是饱和颜色。在色彩空间方面,这暗示了一些类似于Hue, Saturation, Lightness color space的东西,如维基百科图片所示:
要将此映射回上面的示例,我怀疑接近0.0的权重将接近双锥的顶部,接近10.0的权重将接近双锥的底部,并且由这些权重调整的类别所表示的颜色具有固定的色调和饱和度(名义上接近双锥的赤道)。
下面的perl代码将hsl颜色转换为rgb。它是adapted from this StackOverflow answer,而这又是改编自我在上面链接的维基百科页面。这只是必要解决方案的一部分:
##
## Converts an HSL color value to RGB. Conversion formula
## adapted from http://en.wikipedia.org/wiki/HSL_color_space.
## Assumes h, s, and l are contained in the set [0, 1] and
## returns r, g, and b in the set [0, 255].
##
## @param Number h The hue
## @param Number s The saturation
## @param Number l The lightness
## @return Array The RGB representation
##
sub hsl_to_rgb
{
my ($h, $s, $l) = @_;
my ($r, $g, $b);
if ($s == 0)
{
$r = $g = $b = $l; ## achromatic
} else
{
sub hue2rgb
{
my ($p, $q, $t) = @_;
while ($t < 0) { $t += 1; }
while ($t > 1) { $t -= 1; }
if ($t < 1/6) { return $p + ($q - $p) * 6 * $t; }
if ($t < 1/2) { return $q; }
if ($t < 2/3) { return $p + ($q - $p) * (2/3 - $t) * 6; }
return $p;
}
my $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
my $p = 2 * $l - $q;
$r = hue2rgb($p, $q, $h + 1/3);
$g = hue2rgb($p, $q, $h);
$b = hue2rgb($p, $q, $h - 1/3);
}
return [ int($r * 255), int($g * 255), int($b * 255) ];
}
此函数接受HSL颜色,例如,
(0, 1.0, 0.5)
表示纯红色,并返回[ 255, 0, 0 ]
形式的RGB三元组。给你一块拼图。根据我从你的问题陈述中所知道的,你有一组基色,你可以用色调和饱和度来表示,并按类别排序。像这样的:
my %cat_colors =
( # Hue Saturation
cat1 => [ 0.00000, 1.00000 ], # Red
cat2 => [ 0.16667, 1.00000 ], # Yellow
cat3 => [ 0.33333, 1.00000 ], # Green
);
Op更新:这太棒了。要在更多类别中添加颜色,“色调”值可以在以下网站中检查:http://www.color-hex.com/。请注意,例如,此网站将hsl指定为红色是:
0.00 1.00 0.50
。注意:你一定会想玩这些颜色的。如果你有photoshop或其他工具,可以让你看到不同颜色空间的颜色,这可能有助于你为每一个类别选择“基础”颜色,使其完全符合你的要求。对于上面的
hsl_to_rgb
代码,您需要将色调和饱和度值缩放到[0,1]范围内。现在我们如何把这个应用到上面给出的权重参数?如上所述,它直接映射到hsl中的lightness参数,权重0.0映射到白色,权重10.0映射到黑色。(至少,首先,根据你的草图,这似乎是一个很好的起点)在hsl中,1.0是白色的,0.0是黑色的。因此,要将权重映射到亮度,需要这样的表达式:
$lightness = 1 - ($weight / 10);
您可以将其包装在函数中:
sub weight_to_light
{
return 1 - ($_[0] / 10);
}
公式中的最后一部分是将
hsl_to_rgb
返回的rgb映射到html可以使用的内容。其实很简单。下面的短函数将r、g、b值数组从hsl_to_rgb
转换为准备好html的十六进制字符串:sub rgb_to_html_hex
{
return sprintf "#%.2X%.2X%.2X", @{ $_[0] };
}
因此,将所有这些放在一起:如果要生成一个名为
%col4
的散列,给定%col2
和%col3
中的详细信息,该散列包含根据上面的着色模型在html中为对象着色所需的字符串,则需要上面的两个函数%cat_colors
映射和一些类似的代码:my %col4;
foreach my $key (keys %col2)
{
foreach my $i ( 0 .. scalar( @{ $col2{$key} } ) - 1 )
{
my $base_color = $cat_colors{ $col2{$key}->[$i] };
my $rgb_color = hsl_to_rgb( @$base_color,
weight_to_light( $col3{$key}->[$i] ) );
my $html_color = rgb_to_html_hex( $rgb_color );
$col4{$key}->[$i] = $html_color;
}
}
生成
%col4
后,可以使用生成的html字符串为单个实体上色。我的现代html有点生疏,但我知道像<FONT COLOR="#xxxxxx">
这样的结构曾经工作过,而且可能仍然有效。我把它留给您根据计算出的值构造语法上有效且足够现代的html。现在,你必须承认,我对你试图解决的问题以及需要如何解决的问题做了一些大胆的假设。我想,不过,我是在一般的棒球场。如果你有问题,可以留下评论。
还有…为了方便剪切和粘贴,这里有一个快速测试程序,我将上面的所有位以及您的示例数据集复制到一个独立的、可测试的perl程序中。享受吧!最后两行使用yaml::xs转储
%col4
的计算值,这样我就可以看到它们是否合理。#!/usr/bin/perl -w
use Modern::Perl;
##
## Converts an HSL color value to RGB. Conversion formula
## adapted from http://en.wikipedia.org/wiki/HSL_color_space.
## Assumes h, s, and l are contained in the set [0, 1] and
## returns r, g, and b in the set [0, 255].
##
## @param Number h The hue
## @param Number s The saturation
## @param Number l The lightness
## @return Array The RGB representation
##
sub hsl_to_rgb
{
my ($h, $s, $l) = @_;
my ($r, $g, $b);
if ($s == 0)
{
$r = $g = $b = $l; ## achromatic
} else
{
sub hue2rgb
{
my ($p, $q, $t) = @_;
while ($t < 0) { $t += 1; }
while ($t > 1) { $t -= 1; }
if ($t < 1/6) { return $p + ($q - $p) * 6 * $t; }
if ($t < 1/2) { return $q; }
if ($t < 2/3) { return $p + ($q - $p) * (2/3 - $t) * 6; }
return $p;
}
my $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
my $p = 2 * $l - $q;
$r = hue2rgb($p, $q, $h + 1/3);
$g = hue2rgb($p, $q, $h);
$b = hue2rgb($p, $q, $h - 1/3);
}
return [ int($r * 255), int($g * 255), int($b * 255) ];
}
sub rgb_to_html_hex
{
return sprintf "#%.2X%.2X%.2X", @{ $_[0] };
}
my %col1 = ( 'foo' => 1, 'bar' => 1 );
my %col2 = ('foo' => ['cat1','cat1','cat2'],
'bar' => ['cat3','cat2','cat3'] );
my %col3 = ('foo' => [2.3,1.2,1.0],
'bar' => [7.4,4.3,2.2]);
my %cat_colors =
( # Hue Saturation
cat1 => [ 0.00000, 1.00000 ], # Red
cat2 => [ 0.16667, 1.00000 ], # Yellow
cat3 => [ 0.33333, 1.00000 ], # Green
);
sub weight_to_light
{
return 1 - ($_[0] / 10);
}
my %col4;
foreach my $key (keys %col2)
{
foreach my $i ( 0 .. scalar( @{ $col2{$key} } ) - 1 )
{
my $base_color = $cat_colors{ $col2{$key}->[$i] };
my $rgb_color = hsl_to_rgb( @$base_color,
weight_to_light( $col3{$key}->[$i] ) );
my $html_color = rgb_to_html_hex( $rgb_color );
$col4{$key}->[$i] = $html_color;
}
}
use YAML::XS;
say Dump( \%col4 );
关于html - 如何使用Perl基于值的刻度为HTML形状创建颜色渐变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19996703/