【问题标题】:compute colors along gradient沿渐变计算颜色
【发布时间】:2014-08-21 07:49:30
【问题描述】:

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

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

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

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;
}

生产出来的:

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

【问题讨论】:

  • 不回答这个问题,但你可以只减去然后取绝对值,而不是把range变量搞得一团糟。
  • 还有一个名为Color的类,它有像decode这样的方法,它接受一个十六进制字符串并将其转换为颜色。从那里它有像getRedgetBluegetGreen这样的方法。
  • CSS 编译器或 javaScript 例程在这里可能会有所帮助 :) codepen.io/gc-nomade/pen/ztDCn(此处使用 scss)
  • javascripted ,包括 IE8 codepen.io/IE-Tests/pen/BIwJm 任何反馈表示感谢。

标签: java html css


【解决方案1】:

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

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

对于懒惰的反应,我很抱歉,但我试图证明的是,在两种颜色之间获取颜色实际上只是第一个颜色分量的百分比加上第二个分量的倒数百分比。至少我是这样处理渐变的。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      通过使用范围变量计算(伪)绝对值,您将失去符号,而您实际上并不想这样做。去掉这个并做简单的减法,代码就可以工作了:

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

      这是生成的结果(当然仅限 IE):

      http://jsfiddle.net/Tz273/

      【讨论】:

      • 这仍然没有给出我正在寻找的外观(但确实使我的代码更清晰)。
      • @BobStout 我认为您的评论是在我编辑之前。我相信更新后的答案可以解决您的问题,因为小提琴与您所需输出的图像相匹配(在 IE9 中)。
      【解决方案4】:

      您可以通过 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 生成 100 个从 1% 到 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 */
      

      【讨论】:

        猜你喜欢
        • 2010-09-24
        • 1970-01-01
        • 2014-05-01
        • 2020-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多