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)
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)
Share Improve this question edited May 23, 2017 at 12:26 CommunityBot 11 silver badge asked Apr 10, 2015 at 7:23 Riaan WaltersRiaan Walters 2,6762 gold badges21 silver badges30 bronze badges 8- what about 4 and 2? 1 green 3 yellow 5 red for cell color? – huan feng Commented Apr 10, 2015 at 7:27
- 2 = between yellow and green, its a color range, not hard set colors, if i had 20 values, the color's would be evenly spread from green - red in each cell. – Riaan Walters Commented Apr 10, 2015 at 7:28
- ok, you just need a dynamic range, like d3 color range – huan feng Commented Apr 10, 2015 at 7:29
- Yes, but i cant use D3 – Riaan Walters Commented Apr 10, 2015 at 7:30
- I added a excel example of what i need – Riaan Walters Commented Apr 10, 2015 at 7:31
3 Answers
Reset to default 5Along 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./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