沿梯度计算颜色

时间:2014-06-30 20:44:13

标签: java html css

有没有办法沿渐变计算颜色?

例如,我有一个标签,我将其用作一种状态栏,其渐变背景一端为绿色(#6bba70),另一端为红色(#a90329)。我想做的是弄清楚渐变中某个点的颜色。例如,如果该过程完成了27%,我希望获得沿着渐变" 27%的颜色。像这样:

desired effect

我想也许我可以找到数字移位,它会给我正确的颜色。我写的代码(不起作用):

public static String getHTML(Date d, int shift) throws SQLException, ClassNotFoundException {
    String returnValue = "";

   returnValue += "        <style type=\"text/css\">\n"
            + "        \n"
            + "            .status{\n"
            + "                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6bba70', endColorstr='" + getColor(77) + "',GradientType=1 );\n"
            + "                width: " + 500 * .77 + "px;\n"
            + "                height: 5px;\n"
            + "                border: thin black solid;\n"
            + "            }\n"
            + "            .status2{\n"
            + "                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6bba70', endColorstr='" + getColor(100) + "',GradientType=1 );\n"
            + "                width: " + 500 + "px;\n"
            + "                height: 5px;\n"
            + "                border: thin black solid;\n"
            + "            }\n"
            + "            .status3{\n"
            + "                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6bba70', endColorstr='" + getColor(33) + "',GradientType=1 );\n"
            + "                width: " + 500 * .33 + "px;\n"
            + "                height: 5px;\n"
            + "                border: thin black solid;\n"
            + "            }\n"
            + "            .status4{\n"
            + "                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6bba70', endColorstr='" + getColor(69) + "',GradientType=1 );\n"
            + "                width: " + 500 * .69 + "px;\n"
            + "                height: 5px;\n"
            + "                border: thin black solid;\n"
            + "            }\n"
            + "        </style>"
            + "    <body>\n"
            + "        77%&nbsp;&nbsp;&nbsp;&nbsp;<label class=\"status\"></label><br><br>\n"
            + "        100%&nbsp;&nbsp;<label class=\"status2\"></label><br><br>\n"
            + "        33%&nbsp;&nbsp;&nbsp;&nbsp;<label class=\"status3\"></label><br><br>\n"
            + "        69%&nbsp;&nbsp;&nbsp;&nbsp;<label class=\"status4\"></label><br><br>\n"
            + "    </body>";
    return returnValue;
}

private static String getColor(double percentage) {
    String colorValue = "";
    int[] rgb1 = getRGB("a90329");
    int[] rgb2 = getRGB("6bba70");

    if (percentage < 100) {

        int range0 = (rgb1[0] > rgb2[0] ? rgb1[0] : rgb2[0]) - (rgb1[0] < rgb2[0] ? rgb1[0] : rgb2[0]);
        int range1 = (rgb1[1] > rgb2[1] ? rgb1[1] : rgb2[1]) - (rgb1[1] < rgb2[1] ? rgb1[1] : rgb2[1]);
        int range2 = (rgb1[2] > rgb2[2] ? rgb1[2] : rgb2[2]) - (rgb1[2] < rgb2[2] ? rgb1[2] : rgb2[2]);

        int r = (int) (rgb2[0] + Math.round(range0 * percentage / 100));
        int g = (int) (rgb2[1] + Math.round(range1 * percentage / 100));
        int b = (int) (rgb2[2] + Math.round(range2 * percentage / 100));


        System.out.println(Integer.toString(r) + "," + Integer.toString(g) + "," + Integer.toString(b));
        colorValue = String.format("#%02x%02x%02x", r, g, b);
    } else {
        colorValue = "#a90329";
    }

    return colorValue;
}

public static int[] getRGB(final String rgb) {
    final int[] ret = new int[3];
    for (int i = 0; i < 3; i++) {
        ret[i] = Integer.parseInt(rgb.substring(i * 2, i * 2 + 2), 16);
    }
    return ret;
}

那产生了:

realizedEffect

远不及我想要的地方。有人知道如何实现我的目标吗?

4 个答案:

答案 0 :(得分:3)

由于渐变是两种颜色之间的补间,我假设它的作用类似于:

int[] start = getRGB("start color here");
int[] end = getRGB("end color here");
double i = 25; // Let i be the percent from start to end, 25 is arbitrary
int newred = (i / 100.0) * start[0] + (1.0 - i / 100.0) * end[0];
// I am sure you can figure out the other two

对于懒惰的回应感到抱歉,但我试图证明的是,在'两种颜色之间'获得颜色实际上只是第一个颜色分量的百分比加上第二个分量的反向百分比。至少这就是我做渐变的方式。

答案 1 :(得分:0)

颜色被分解(通常)为3个值,范围从0到255,每个值代表红绿色或蓝色(分别)的量。您需要找到绿色和红色的初始值,以及绿色和红色的最终值。例如,我们会让它变得简单。假设你的起始值是100绿色和0红色。然后让我们说你的最终值是0绿色和100红色。您需要做的就是将每个值的范围从0到100映射。我方便地选择了我所做的数字,因此映射很容易。所以假设你是25%,你的绿色值是75,你的红色值是25。当然,如果他们的值是0到100,它很可能不会有效,但无论如何,它是将一个数字范围映射到另一个范围很简单。看看这个甜蜜的SO问题:How to scale down a range of numbers with a known min and max value

答案 2 :(得分:0)

通过使用范围变量执行(伪)绝对值,您将失去您实际上不想做的符号。删除它并执行简单的减法,代码可以正常工作:

int range0 = rgb1[0] - rgb2[0];
int range1 = rgb1[1] - rgb2[1];
int range2 = rgb1[2] - rgb2[2];

这是生成的结果(当然只有IE):

http://jsfiddle.net/Tz273/

答案 3 :(得分:0)

您可以通过jQuery循环将宽度设置为标签,并通过CSS管理渐变。的 CSS + jQuery Demo

$("div[data-status]").each(function(index, value) {
   dataw = $(this).attr('data-status');
  $(this).children('label').css('width',dataw+'%');
});

另外,使用CSS编译器,您也可以获得一些乐趣: CSS + SCSS DEMO ,从1%到100%宽度生成100个标签并生成关联样式。

HTML或多或少是这样的:

<div data-status='2'>
  <label>status</label>
</div>

和CSS是

[data-status] {
  overflow:hidden;
  position:relative;
  box-sizing:border-box;
  margin:1em;
  padding-left:3.5em;
  background:linear-gradient(
    to right,transparent 3em,#6bba70 3em ,#a90329);
}
[data-status]:before {
  position:absolute;
  content:attr(data-status)'%';
  width:2.5em;
  left:0;
  top:0.2em;
  text-align:right;
}
[data-status] label {
  display:inline-block;
  color:rgba(0,0,0,0); 
  border:solid black;
  box-sizing:border-box;
  margin-left:-0.6em;
  box-shadow:1000px 0 0  1000px white;
}

生成规则的SCSS例程(这可能是你的想法,除非你在js / jQuery方面这样做)

$n : 100 ;
@for $i from 0 through $n {
  @if $i > 0
  {
    [data-status="#{$i}"] label
    {
      width : #{$i + 0%}  ;
    }
  }
}

关于IE8的兼容性?的 DEMO

您需要在建议的CSS前添加:

/* ie 8 */
div {
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6bba70', endColorstr='#a90329',GradientType=1);
}
div label {
  outline:1000px solid white;
  color:transparent;
}
/* end ie 8 */

IE8 render