blob: 1f444dc4fa6671480704e8326939db35fc3b5072 [file] [log] [blame]
Eugenia Gabrielova8b34c652013-10-19 06:53:27 -07001/*
2RainbowVis-JS
3Released under MIT License
4
5Source: https://github.com/anomal/RainbowVis-JS
6*/
7
8function Rainbow()
9{
10 var gradients = null;
11 var minNum = 0;
12 var maxNum = 100;
13 var colours = ['ff0000', 'ffff00', '00ff00', '0000ff'];
14 setColours(colours);
15
16 function setColours (spectrum)
17 {
18 if (spectrum.length < 2) {
19 throw new Error('Rainbow must have two or more colours.');
20 } else {
21 var increment = (maxNum - minNum)/(spectrum.length - 1);
22 var firstGradient = new ColourGradient();
23 firstGradient.setGradient(spectrum[0], spectrum[1]);
24 firstGradient.setNumberRange(minNum, minNum + increment);
25 gradients = [ firstGradient ];
26
27 for (var i = 1; i < spectrum.length - 1; i++) {
28 var colourGradient = new ColourGradient();
29 colourGradient.setGradient(spectrum[i], spectrum[i + 1]);
30 colourGradient.setNumberRange(minNum + increment * i, minNum + increment * (i + 1));
31 gradients[i] = colourGradient;
32 }
33
34 colours = spectrum;
35 return this;
36 }
37 }
38
39 this.setColors = this.setColours;
40
41 this.setSpectrum = function ()
42 {
43 setColours(arguments);
44 return this;
45 }
46
47 this.setSpectrumByArray = function (array)
48 {
49 setColours(array);
50 return this;
51 }
52
53 this.colourAt = function (number)
54 {
55 if (isNaN(number)) {
56 throw new TypeError(number + ' is not a number');
57 } else if (gradients.length === 1) {
58 return gradients[0].colourAt(number);
59 } else {
60 var segment = (maxNum - minNum)/(gradients.length);
61 var index = Math.min(Math.floor((Math.max(number, minNum) - minNum)/segment), gradients.length - 1);
62 return gradients[index].colourAt(number);
63 }
64 }
65
66 this.colorAt = this.colourAt;
67
68 this.setNumberRange = function (minNumber, maxNumber)
69 {
70 if (maxNumber > minNumber) {
71 minNum = minNumber;
72 maxNum = maxNumber;
73 setColours(colours);
74 } else {
75 throw new RangeError('maxNumber (' + maxNumber + ') is not greater than minNumber (' + minNumber + ')');
76 }
77 return this;
78 }
79}
80
81function ColourGradient()
82{
83 var startColour = 'ff0000';
84 var endColour = '0000ff';
85 var minNum = 0;
86 var maxNum = 100;
87
88 this.setGradient = function (colourStart, colourEnd)
89 {
90 startColour = getHexColour(colourStart);
91 endColour = getHexColour(colourEnd);
92 }
93
94 this.setNumberRange = function (minNumber, maxNumber)
95 {
96 if (maxNumber > minNumber) {
97 minNum = minNumber;
98 maxNum = maxNumber;
99 } else {
100 throw new RangeError('maxNumber (' + maxNumber + ') is not greater than minNumber (' + minNumber + ')');
101 }
102 }
103
104 this.colourAt = function (number)
105 {
106 return calcHex(number, startColour.substring(0,2), endColour.substring(0,2))
107 + calcHex(number, startColour.substring(2,4), endColour.substring(2,4))
108 + calcHex(number, startColour.substring(4,6), endColour.substring(4,6));
109 }
110
111 function calcHex(number, channelStart_Base16, channelEnd_Base16)
112 {
113 var num = number;
114 if (num < minNum) {
115 num = minNum;
116 }
117 if (num > maxNum) {
118 num = maxNum;
119 }
120 var numRange = maxNum - minNum;
121 var cStart_Base10 = parseInt(channelStart_Base16, 16);
122 var cEnd_Base10 = parseInt(channelEnd_Base16, 16);
123 var cPerUnit = (cEnd_Base10 - cStart_Base10)/numRange;
124 var c_Base10 = Math.round(cPerUnit * (num - minNum) + cStart_Base10);
125 return formatHex(c_Base10.toString(16));
126 }
127
128 formatHex = function (hex)
129 {
130 if (hex.length === 1) {
131 return '0' + hex;
132 } else {
133 return hex;
134 }
135 }
136
137 function isHexColour(string)
138 {
139 var regex = /^#?[0-9a-fA-F]{6}$/i;
140 return regex.test(string);
141 }
142
143 function getHexColour(string)
144 {
145 if (isHexColour(string)) {
146 return string.substring(string.length - 6, string.length);
147 } else {
148 var colourNames =
149 [
150 ['red', 'ff0000'],
151 ['lime', '00ff00'],
152 ['blue', '0000ff'],
153 ['yellow', 'ffff00'],
154 ['orange', 'ff8000'],
155 ['aqua', '00ffff'],
156 ['fuchsia', 'ff00ff'],
157 ['white', 'ffffff'],
158 ['black', '000000'],
159 ['gray', '808080'],
160 ['grey', '808080'],
161 ['silver', 'c0c0c0'],
162 ['maroon', '800000'],
163 ['olive', '808000'],
164 ['green', '008000'],
165 ['teal', '008080'],
166 ['navy', '000080'],
167 ['purple', '800080']
168 ];
169 for (var i = 0; i < colourNames.length; i++) {
170 if (string.toLowerCase() === colourNames[i][0]) {
171 return colourNames[i][1];
172 }
173 }
174 throw new Error(string + ' is not a valid colour.');
175 }
176 }
177}
178