Reputation: 2676
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)
Upvotes: 1
Views: 3355
Reputation: 2124
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
Upvotes: 0
Reputation: 486
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
Upvotes: 5
Reputation: 6143
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
Upvotes: 3