2

There is a way for get color from a number? it's mathematically possible?

I have an array of positive number like this:

array(1, 2, 1000, 564, 30, 113) and I need a color (humanly distinguishable) for each of these. I can use PHP or JS for this purpose.

I need this because i'm using http://www.chartjs.org/ with dynamic values.

edit: this is an example from chartjs documentation:

<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});
</script>

In this example are defined 6 bars (red, blue, yellow, green, purple and orange) In my case this bars are dynamically generated and I don't know how many bars I have to show. How I can associate a color for each bar? (this color must be the same everytime page refresh)

icy
  • 1,468
  • 3
  • 16
  • 36

1 Answers1

4

Using a method from https://stackoverflow.com/a/2262117/2737978 you can convert an integer into an rgb value.

$("#slider1").on("input", function() {
  var value = $(this).val();
  var rgbColor = intToRGB(value);

  $(".number").html(value);
  $(".example").css('background-color', rgbColor);

});

var intToRGB = function(value) {
  //credit to https://stackoverflow.com/a/2262117/2737978 for the idea of how to implement
  var blue = Math.floor(value % 256);
  var green = Math.floor(value / 256 % 256);
  var red = Math.floor(value / 256 / 256 % 256);

  return "rgb(" + red + "," + green + "," + blue + ")";
}
#slider1 {
  width: 100%
}

.example {
  width: 50px;
  height: 50px;
  margin 0 auto;
  background-color: #000000;
  transition: background-color 100ms ease-in;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="slider1" type="range" min="0" max="16777215" step="1" value="0" />
<div class="number">0</div>
<div class="example"></div>

You would just need to use the intToRGB function in your code. Perhaps though if your numbers are all between 1-1000 you might not see such a gradient so would need to adjust the values (either the 256 or adjust the value going in by a certain factor)

---UPDATE

and here is a live example using your graph and a large factor to give a nice range of colour. You would probably want to add some validation into this to ensure the data does not go above the max but here is a quick go.

Here the int to RGB function has been updated to take in a max value that you would like to represent the top colour. On this a scale can more easily be created to give more diversity between ints, depending on your max the colours will be different as they land on a different part of the overall scale of what can be represented.

var intToRGB = function(value, alpha, max) {
  var valueAsPercentageOfMax = value / max;
  // actual max is 16777215 but represnts white so we will take a max that is
  // below this to avoid white
  var MAX_RGB_INT = 16600000;
  var valueFromMaxRgbInt = Math.floor(MAX_RGB_INT * valueAsPercentageOfMax);
  
  //credit to https://stackoverflow.com/a/2262117/2737978 for the idea of how to implement
  var blue = Math.floor(valueFromMaxRgbInt % 256);
  var green = Math.floor(valueFromMaxRgbInt / 256 % 256);
  var red = Math.floor(valueFromMaxRgbInt / 256 / 256 % 256);
 
  return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")";
}

var data = [12, 19, 3, 5, 2, 3];

var MAX = 19;

var backgroundColors = data.map(function(item) {
  return intToRGB(item, 0.8, MAX);
});

var borderColors = data.map(function(item) {
  return intToRGB(item, 1, MAX);
});
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: data,
      backgroundColor: backgroundColors,
      borderColor: borderColors,
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.js"></script>
<canvas id="myChart" width="400" height="400">
</canvas>
Quince
  • 14,790
  • 6
  • 60
  • 69
  • Nice, the only bad thing is range color. I have tried with high factor but some colors are nearly identical – icy Jun 09 '17 at 08:35
  • Ok, updated the answer to try and give better control over the range when dealing with a smaller range of possible values – Quince Jun 09 '17 at 09:40
  • I didn't test it, but I really appreciate your help, Quince – icy Jun 09 '17 at 09:51
  • quite alright, let me know if it doesn't work out / can be improved – Quince Jun 09 '17 at 09:53