简体   繁体   中英

Color range - table values in angular

Lets assume we have the following setup (bellow), I want the table to have 5 cells, which it will, but i want the 5 cells to have a dynamic color range which goes from green to red (1 = green, 3 = yellow, 5 = red, ect)

The only technologies I am allowed to work with is : CSS3 / HTML5 / Angular - I am allowed to work with any angular lib

In excel its trivial doing this, but since im fairly new to angular, i'm admittedly a bit lost.

~ Script
var arrayWith5Values = [1,2,3,4,5]
~
    <table>
        <tr>
           <td ng-repeat='numericValue in arrayWith5Values'>
              {{numericValue}}}
           </td>
        </tr>
    </table>

It's basicly the angular version of this question : Coloring HTML table cells from "Low to High Color Shades" depending on Cell Value in Python HTML Email and this Color Cell Based on Value in Cell

I have been searching StackOverflow for the majority of last night and could not find an answer.

Here is an example (screenshot from excel)例子

Along the same lines of Kirill Slatin's answer, but this one is a lot simpler:

HTML:

<table>
    <tr>
       <td ng-repeat='numericValue in arrayWith5Values' style="background-color: rgb({{getColor($index)}})"
        ng-init="$parent.numValues = arrayWith5Values.length">
          {{numericValue}}
       </td>
    </tr>
 </table>

Controller JS:

$scope.arrayWith5Values = [1,2,3,4,5,6,7,8,9,10];
$scope.getColor = function(index) {
    var greenVal = Math.round(Math.min((255.0*2.0)*(index/($scope.numValues-1)), 255));
    var redVal = Math.round(Math.min((255.0*2.0)*(($scope.numValues-1-index)/($scope.numValues-1))));
    return "" + greenVal + "," + redVal + ",0";
}

Seemed to be working pretty well with the little testing I did. JSFiddle here

Note: this is tailored specifically for green to red. This same math could be applied to other color schemes, but it would have to be somewhat manually done again

Pure Angular and javascript. Javascript code quality is not good, but it is here just for you to get the idea. I was really writing fast...

IDEA : use custom function ( getColor() ) to define the background color or your elements. Mind that curly braces {{}} in Angular add $watch expressions. So I suggest using once-binding via {{::}} if you have fresh enough Angular (v1.3+). Otherwise use the angular library BindOnce

HTML :

   <tr ng-repeat="arr in data">
        <td ng-repeat="value in arr" ng-attr-style="background: #{{::getColor(value, arr)}};">
            {{value}}
        </td>
    </tr>

Javascript :

$scope.getColor = function(item, array){
    var h = item / array.length ;
    return RGBtoHex(HSVtoRGB(h, 1, 1))
};
function RGBtoHex(color){
    var r = color.r.toString(16);
    if(r.length < 2) r = '0' + r;
    var g = color.g.toString(16);
    if(g.length < 2) g = '0' + g;
    var b = color.b.toString(16);
    if(b.length < 2) b = '0' + b;
    return r + g + b;
}

function HSVtoRGB(h, s, v) {
    var r, g, b, i, f, p, q, t;
    if (h && s === undefined && v === undefined) {
        s = h.s, v = h.v, h = h.h;
    }
    i = Math.floor(h * 6);
    f = h * 6 - i;
    p = v * (1 - s);
    q = v * (1 - f * s);
    t = v * (1 - (1 - f) * s);
    switch (i % 6) {
        case 0: r = v, g = t, b = p; break;
        case 1: r = q, g = v, b = p; break;
        case 2: r = p, g = v, b = t; break;
        case 3: r = p, g = q, b = v; break;
        case 4: r = t, g = p, b = v; break;
        case 5: r = v, g = p, b = q; break;
    }
    return {
        r: Math.floor(r * 255),
        g: Math.floor(g * 255),
        b: Math.floor(b * 255)
    };

PS : getColor() is function you need to redefine according to you color palette. Mind that Hue in HSV color model changes from 0 to 1 ranging the whole spectrum. You should select which range of the spectrum you would like to achieve from first till last element and accordingly limit in function. Although handle marginal cases (like 1 or 2 elements) based on your specification.

Working example in this jsfiddle

Credits for HSVToRGB() goes for Paul S. https://stackoverflow.com/a/17243070/4573999

If anyone else stumbled upon this and wasn't as satisfied as I was with the provided solution, I hacked together another solution.

I wanted to be able to use an array of values and color scale them from lowest red to highest green as well as use a midpoint color as yellow.

Take a look below as well as at the fiddle to see a working solution.

ctrl.getColor = function(value, min_value, max_value) {
    let [highMaxR, highMaxG, highMaxB] = [99, 190, 123];
    let [lowMaxR, lowMaxG, lowMaxB] = [248, 105, 107];
    let [midMaxR, midMaxG, midMaxB] = [255, 235, 132];

    if (Math.round(max_value - min_value) === 0) return `${highMaxR}, ${highMaxG}, ${highMaxB}`;

    let mid_point = (max_value + min_value) / 2;
    if (value > mid_point) {
      [lowMaxR, lowMaxG, lowMaxB] = [midMaxR, midMaxG, midMaxB];
      min_value = mid_point;
    } else {
      [highMaxR, highMaxG, highMaxB] = [midMaxR, midMaxG, midMaxB];
      max_value = mid_point;
    }

    let percentage = Math.abs((value - min_value) / (max_value - min_value));

    let redVal = Math.round(lowMaxR + ((highMaxR - lowMaxR) * percentage));
    let greenVal = Math.round(lowMaxG + ((highMaxG - lowMaxG) * percentage));
    let blueVal = Math.round(lowMaxB + ((highMaxB - lowMaxB) * percentage));

    return `${redVal}, ${greenVal}, ${blueVal}`;
};

Here is the fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM