plotboilerplate 1.12.7 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +4 -1
  2. package/changelog.md +25 -0
  3. package/dist/index.esm.js +259 -44
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.esm.min.js +1 -1
  6. package/dist/index.esm.min.js.map +1 -1
  7. package/dist/plotboilerplate.browser.min.js +1 -1
  8. package/dist/plotboilerplate.browser.min.js.map +1 -1
  9. package/dist/plotboilerplate.js +273 -43
  10. package/dist/plotboilerplate.min.js +1 -1
  11. package/package.json +1 -1
  12. package/src/cjs/PBText.d.ts +116 -0
  13. package/src/cjs/PBText.js +66 -0
  14. package/src/cjs/PBText.js.map +1 -0
  15. package/src/cjs/PlotBoilerplate.d.ts +2 -1
  16. package/src/cjs/PlotBoilerplate.js +66 -19
  17. package/src/cjs/PlotBoilerplate.js.map +1 -1
  18. package/src/cjs/draw.d.ts +30 -2
  19. package/src/cjs/draw.js +51 -6
  20. package/src/cjs/draw.js.map +1 -1
  21. package/src/cjs/drawgl.d.ts +29 -2
  22. package/src/cjs/drawgl.js +21 -4
  23. package/src/cjs/drawgl.js.map +1 -1
  24. package/src/cjs/drawutilssvg.d.ts +25 -7
  25. package/src/cjs/drawutilssvg.js +62 -14
  26. package/src/cjs/drawutilssvg.js.map +1 -1
  27. package/src/cjs/entry.js +1 -0
  28. package/src/cjs/index.d.ts +1 -0
  29. package/src/cjs/index.js +1 -0
  30. package/src/cjs/index.js.map +1 -1
  31. package/src/cjs/interfaces/DrawLib.d.ts +27 -6
  32. package/src/cjs/interfaces/DrawLib.js +3 -0
  33. package/src/cjs/interfaces/DrawLib.js.map +1 -1
  34. package/src/cjs/interfaces/core.d.ts +12 -1
  35. package/src/cjs/interfaces/core.js +1 -0
  36. package/src/cjs/interfaces/core.js.map +1 -1
  37. package/src/cjs/utils/datastructures/Color.d.ts +28 -15
  38. package/src/cjs/utils/datastructures/Color.js +276 -88
  39. package/src/cjs/utils/datastructures/Color.js.map +1 -1
  40. package/src/esm/PBText.d.ts +116 -0
  41. package/src/esm/PBText.js +61 -0
  42. package/src/esm/PBText.js.map +1 -0
  43. package/src/esm/PlotBoilerplate.d.ts +2 -1
  44. package/src/esm/PlotBoilerplate.js +66 -19
  45. package/src/esm/PlotBoilerplate.js.map +1 -1
  46. package/src/esm/draw.d.ts +30 -2
  47. package/src/esm/draw.js +51 -6
  48. package/src/esm/draw.js.map +1 -1
  49. package/src/esm/drawgl.d.ts +29 -2
  50. package/src/esm/drawgl.js +21 -4
  51. package/src/esm/drawgl.js.map +1 -1
  52. package/src/esm/drawutilssvg.d.ts +25 -7
  53. package/src/esm/drawutilssvg.js +62 -14
  54. package/src/esm/drawutilssvg.js.map +1 -1
  55. package/src/esm/entry.js +1 -0
  56. package/src/esm/index.d.ts +1 -0
  57. package/src/esm/index.js +1 -0
  58. package/src/esm/index.js.map +1 -1
  59. package/src/esm/interfaces/DrawLib.d.ts +27 -6
  60. package/src/esm/interfaces/DrawLib.js +3 -0
  61. package/src/esm/interfaces/DrawLib.js.map +1 -1
  62. package/src/esm/interfaces/core.d.ts +12 -1
  63. package/src/esm/interfaces/core.js +1 -0
  64. package/src/esm/interfaces/core.js.map +1 -1
  65. package/src/esm/utils/datastructures/Color.d.ts +28 -15
  66. package/src/esm/utils/datastructures/Color.js +277 -89
  67. package/src/esm/utils/datastructures/Color.js.map +1 -1
  68. package/src/ts/PBText.ts +147 -0
  69. package/src/ts/PlotBoilerplate.ts +74 -23
  70. package/src/ts/draw.ts +71 -8
  71. package/src/ts/drawgl.ts +48 -8
  72. package/src/ts/drawutilssvg.ts +94 -17
  73. package/src/ts/index.ts +1 -0
  74. package/src/ts/interfaces/DrawLib.ts +30 -4
  75. package/src/ts/interfaces/core.ts +12 -0
  76. package/src/ts/utils/datastructures/Color.ts +695 -508
  77. package/src/ts/utils/algorithms/clearPolygonDuplicateVertices.ts~ +0 -5
  78. package/src/ts/utils/algorithms/findPolygonSelfIntersections.ts~ +0 -45
  79. package/src/ts/utils/algorithms/splitPolygonToNonIntersecting.ts~ +0 -113
  80. package/src/ts/utils/algorithms/sutherlandHodgman.ts~ +0 -88
  81. package/src/ts/utils/datastructures/Color.ts~ +0 -331
  82. package/src/ts/utils/datastructures/Girih.ts~ +0 -151
  83. package/src/ts/utils/datastructures/GirihTile.ts~ +0 -419
@@ -8,527 +8,714 @@
8
8
  * @modified 2020-10-23 Ported to Typescript.
9
9
  * @modified 2021-02-08 Fixed a lot of es2015 compatibility issues.
10
10
  * @modified 2021-02-08 Added basic tsdoc/jsdoc comments.
11
- * @version 0.0.9
11
+ * @modified 2021-11-05 Fixing the regex to parse rgba-strings.
12
+ * @modified 2021-11-05 Added return value `this` to all modifier functions (for chaining).
13
+ * @modified 2021-11-07 Changed the behavior of `darken` and `lighten`: the passed value is handled relative now which makes values much easier predictable and makes the change feel more 'natural'.
14
+ * @modified 2021-11-07 Did the same with `saturate` and `desaturate`.
15
+ * @modified 2021-11-07 Did the same with the `fadein` and `fadeout` functions.
16
+ * @modified 2021-11-07 Added setRed, setGreen, setBlue, setHue, setSaturation, setLiminance functions.
17
+ * @version 0.0.10
12
18
  **/
13
19
 
14
-
15
20
  /**
16
- * @classdesc A color class, inspired by neolitec's Javascript class.
21
+ * @classdesc A color class, inspired by neolitec's Javascript class.
17
22
  * Original found at
18
23
  * https://gist.github.com/neolitec/1344610
19
24
  * Thanks to neolitec
20
25
  */
21
26
  export class Color {
22
-
23
- /**
24
- * @member {number}
25
- * @memberof Color
26
- * @instance
27
- */
28
- r : number;
29
-
30
- /**
31
- * @member {number}
32
- * @memberof Color
33
- * @instance
34
- */
35
- g : number;
36
-
37
- /**
38
- * @member {number}
39
- * @memberof Color
40
- * @instance
41
- */
42
- b : number;
43
-
44
- /**
45
- * @member {number}
46
- * @memberof Color
47
- * @instance
48
- */
49
- h : number;
50
-
51
- /**
52
- * @member {number}
53
- * @memberof Color
54
- * @instance
55
- */
56
- s : number;
57
-
58
- /**
59
- * @member {number}
60
- * @memberof Color
61
- * @instance
62
- */
63
- l : number;
64
-
65
- /**
66
- * @member {number}
67
- * @memberof Color
68
- * @instance
69
- */
70
- a : number;
71
-
72
- /**
73
- * Construct a new color with `r=0 g=0 b=0`.
74
- *
75
- * Consider using the `makeHex`, `makeRGB` or `makeHSL` functions.
76
- *
77
- * @constructor
78
- * @instance
79
- * @memberof Color
80
- */
81
- constructor() {
82
- this.r = this.g = this.b = 0;
83
- this.h = this.s = this.l = 0;
84
- this.a = 1;
85
- };
86
-
87
- // --- RGB ----------------------------------
88
- /**
89
- * Get this color as a CSS `rgb` string.
90
- *
91
- * Consult this for details: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
92
- *
93
- * @method cssRGB
94
- * @instance
95
- * @memberof Color
96
- * @return {string} This color as a CSS rgb string.
97
- */
98
- cssRGB() : string {
99
- return "rgb("+Math.round(255*this.r)+","+Math.round(255*this.g)+","+Math.round(255*this.b)+")";
100
- };
101
-
102
-
103
- /**
104
- * Get this color as a CSS `rgba` string.
105
- *
106
- * Consult this for details: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
107
- *
108
- * @method cssRGBA
109
- * @instance
110
- * @memberof Color
111
- * @return {string} This color as a CSS rgba string.
112
- */
113
- cssRGBA() : string {
114
- return "rgba("+Math.round(255*this.r)+","+Math.round(255*this.g)+","+Math.round(255*this.b)+","+this.a+")";
115
- };
116
-
117
- /**
118
- * Get the red component of this RGB(A)color. This method just returns the `r` color attribute.
119
- *
120
- * @method red
121
- * @instance
122
- * @memberof Color
123
- * @return {number} A value between 0.0 and 1.0.
124
- */
125
- red() : number { return this.r; };
126
-
127
- /**
128
- * Get the green component of this RGB(A) color. This method just returns the `g` color attribute.
129
- *
130
- * @method green
131
- * @instance
132
- * @memberof Color
133
- * @return {number} A value between 0.0 and 1.0.
134
- */
135
- green() : number { return this.g; };
136
-
137
- /**
138
- * Get the blue component of this RGB(A) color. This method just returns the `b` color attribute.
139
- *
140
- * @method blue
141
- * @instance
142
- * @memberof Color
143
- * @return {number} A value between 0.0 and 1.0.
144
- */
145
- blue() : number { return this.b; };
146
-
147
-
148
- // --- HSL ----------------------------------
149
- /**
150
- * Get this color as a CSS `hsl` string.
151
- *
152
- * @method cssHSL
153
- * @instance
154
- * @memberof Color
155
- * @return {string} This color as a CSS hsl string.
156
- */
157
- cssHSL() : string {
158
- return "hsl("+Math.round(360*this.h)+","+Math.round(100*this.s)+"%,"+Math.round(100*this.l)+"%)";
159
- };
160
-
161
- /**
162
- * Get this color as a CSS `hsla` string.
163
- *
164
- * @method cssHSLA
165
- * @instance
166
- * @memberof Color
167
- * @return {string} This color as a CSS hsla string.
168
- */
169
- cssHSLA() : string {
170
- return "hsla("+Math.round(360*this.h)+","+Math.round(100*this.s)+"%,"+Math.round(100*this.l)+"%,"+Math.round(this.a)+")";
171
- };
172
-
173
-
174
- /**
175
- * Get the hue component of this HSL(A) color. This method just returns the `h` color attribute.
176
- *
177
- * @method hue
178
- * @instance
179
- * @memberof Color
180
- * @return {number} A value between 0.0 and 1.0.
181
- */
182
- hue() : number { return this.h; };
183
-
184
-
185
- /**
186
- * Get the saturation component of this HSL(A) color. This method just returns the `s` color attribute.
187
- *
188
- * @method saturation
189
- * @instance
190
- * @memberof Color
191
- * @return {number} A value between 0.0 and 1.0.
192
- */
193
- saturation() : number { return this.s; };
194
-
195
-
196
- /**
197
- * Get the lightness component of this HSL(A) color. This method just returns the `l` color attribute.
198
- *
199
- * @method lightness
200
- * @instance
201
- * @memberof Color
202
- * @return {number} A value between 0.0 and 1.0.
203
- */
204
- lightness() : number { return this.l; };
205
-
206
-
207
- // --- HEX ----------------------------------
208
- /**
209
- * Get this color as a CSS-HEX string (non-alpha): #rrggbb
210
- *
211
- * @method cssHEX
212
- * @instance
213
- * @memberof Color
214
- * @return {string} This color as a CSS-HEX string.
215
- */
216
- cssHEX() : string {
217
- return "#" +
218
- (255*this.r < 16 ? "0" : "") + Math.round(255*this.r).toString(16) +
219
- (255*this.g < 16 ? "0" : "") + Math.round(255*this.g).toString(16) +
220
- (255*this.b < 16 ? "0" : "") + Math.round(255*this.b).toString(16);
221
- };
222
-
223
- // --- Transparency ----------------------------------
224
-
225
- /**
226
- * Get the alpha channel (transparency) of this color.
227
- *
228
- * @method alpha
229
- * @instance
230
- * @memberof Color
231
- * @return {number} A value between 0.0 and 1.0.
232
- */
233
- alpha() : number { return this.a; };
234
-
235
- // --- Modifiers ----------------------------------
236
-
237
- saturate(v:string|number) : void {
238
- if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN)
239
- this.s += v/100;
240
- else if("number" == typeof v) // range 255
241
- this.s += v/255;
242
- else throw new Error("error: bad modifier format (percent or number)");
243
- if(this.s > 1) this.s = 1; else if(this.s < 0) this.s = 0;
244
- Color.Converter.HSLToRGB(this);
245
- };
246
- desaturate(v:string|number) : void {
247
- this.saturate("-" + v);
248
- };
249
- lighten(v:string|number) : void {
250
- if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN)
251
- this.l += v/100;
252
- else if("number" == typeof v) // range 255
253
- this.l += v/255;
254
- else throw new Error("error: bad modifier format (percent or number)");
255
- if(this.l > 1) this.l = 1; else if(this.l < 0) this.l = 0;
256
- Color.Converter.HSLToRGB(this);
257
- };
258
- darken(v:string|number) : void {
259
- this.lighten("-" + v);
260
- };
261
- fadein(v:string|number) : void {
262
- if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN)
263
- this.a += v/100;
264
- else if("number" == typeof v) // range 255
265
- this.a += v/255;
266
- else throw new Error("error: bad modifier format (percent or number)");
267
- if(this.a > 1) this.a = 1; else if(this.a < 0) this.a = 0;
268
- Color.Converter.HSLToRGB(this);
269
- };
270
- fadeout(v:string|number) : void {
271
- this.fadein("-" + v);
272
- };
273
- spin(v:string|number) : void {
274
- if("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN)
275
- this.h += v/100;
276
- else if("number" == typeof v) // range 360
277
- this.h += v/360;
278
- else throw new Error("error: bad modifier format (percent or number)");
279
- if(this.h > 1) this.h = 1; else if(this.h < 0) this.h = 0;
280
- Color.Converter.HSLToRGB(this);
281
- };
282
-
283
- static makeRGB(...args: any[]) : Color {
284
- const c : Color = new Color();
285
- let sanitized : Array<number>;
286
- if(arguments.length < 3 || arguments.length > 4)
287
- throw new Error("error: 3 or 4 arguments");
288
- sanitized = Color.Sanitizer.RGB(arguments[0], arguments[1], arguments[2]);
289
- c.r = sanitized[0];
290
- c.g = sanitized[1];
291
- c.b = sanitized[2];
292
- if(arguments.length == 4) c.a = arguments[3];
293
- Color.Converter.RGBToHSL(c);
294
- return c;
295
- };
296
-
297
- static makeHSL(...args: Array<number|string>) : Color {
298
- const c : Color = new Color();
299
- let sanitized : Array<number>;
300
- if(arguments.length < 3 || arguments.length > 4)
301
- throw new Error("error: 3 or 4 arguments");
302
- sanitized = Color.Sanitizer.HSL(arguments[0], arguments[1], arguments[2]);
303
- c.h = sanitized[0];
304
- c.s = sanitized[1];
305
- c.l = sanitized[2];
306
- if(arguments.length == 4) c.a = arguments[3];
307
- Color.Converter.HSLToRGB(c);
308
- return c;
309
- };
310
-
311
- static makeHEX(value:string) : Color {
312
- var c = new Color(),
313
- sanitized;
314
- // Edit Ika 2018-0308
315
- // Allow leading '#'
316
- if( value && value.startsWith('#') )
317
- value = value.substr(1);
318
- Color.Validator.checkHEX(value);
319
- if(value.length == 3) {
320
- sanitized = Color.Sanitizer.RGB(
321
- parseInt(value.substr(0, 1) + value.substr(0, 1), 16),
322
- parseInt(value.substr(1, 1) + value.substr(1, 1), 16),
323
- parseInt(value.substr(2, 1) + value.substr(2, 1), 16)
324
- );
325
- } else if(value.length == 6) {
326
- sanitized = Color.Sanitizer.RGB(
327
- parseInt(value.substr(0, 2), 16),
328
- parseInt(value.substr(2, 2), 16),
329
- parseInt(value.substr(4, 2), 16)
330
- );
331
- } else throw new Error("error: 3 or 6 arguments");
332
- c.r = sanitized[0];
333
- c.g = sanitized[1];
334
- c.b = sanitized[2];
335
- Color.Converter.RGBToHSL(c);
336
- return c;
337
- };
338
-
339
-
27
+ /**
28
+ * @member {number}
29
+ * @memberof Color
30
+ * @instance
31
+ */
32
+ r: number;
33
+
34
+ /**
35
+ * @member {number}
36
+ * @memberof Color
37
+ * @instance
38
+ */
39
+ g: number;
40
+
41
+ /**
42
+ * @member {number}
43
+ * @memberof Color
44
+ * @instance
45
+ */
46
+ b: number;
47
+
48
+ /**
49
+ * @member {number}
50
+ * @memberof Color
51
+ * @instance
52
+ */
53
+ h: number;
54
+
55
+ /**
56
+ * @member {number}
57
+ * @memberof Color
58
+ * @instance
59
+ */
60
+ s: number;
61
+
62
+ /**
63
+ * @member {number}
64
+ * @memberof Color
65
+ * @instance
66
+ */
67
+ l: number;
68
+
69
+ /**
70
+ * @member {number}
71
+ * @memberof Color
72
+ * @instance
73
+ */
74
+ a: number;
75
+
76
+ /**
77
+ * Construct a new color with `r=0 g=0 b=0`.
78
+ *
79
+ * Consider using the `makeHex`, `makeRGB` or `makeHSL` functions.
80
+ *
81
+ * @constructor
82
+ * @instance
83
+ * @memberof Color
84
+ */
85
+ constructor() {
86
+ this.r = this.g = this.b = 0;
87
+ this.h = this.s = this.l = 0;
88
+ this.a = 1;
89
+ }
90
+
91
+ // --- RGB ----------------------------------
92
+ /**
93
+ * Get this color as a CSS `rgb` string.
94
+ *
95
+ * Consult this for details: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
96
+ *
97
+ * @method cssRGB
98
+ * @instance
99
+ * @memberof Color
100
+ * @return {string} This color as a CSS rgb string.
101
+ */
102
+ cssRGB(): string {
103
+ return "rgb(" + Math.round(255 * this.r) + "," + Math.round(255 * this.g) + "," + Math.round(255 * this.b) + ")";
104
+ }
105
+
106
+ /**
107
+ * Get this color as a CSS `rgba` string.
108
+ *
109
+ * Consult this for details: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
110
+ *
111
+ * @method cssRGBA
112
+ * @instance
113
+ * @memberof Color
114
+ * @return {string} This color as a CSS rgba string.
115
+ */
116
+ cssRGBA(): string {
117
+ return `rgba(${Math.round(255 * this.r)},${Math.round(255 * this.g)},${Math.round(255 * this.b)},${this.a})`;
118
+ }
119
+
120
+ /**
121
+ * Get the red component of this RGB(A)color. This method just returns the `r` color attribute.
122
+ *
123
+ * @method red
124
+ * @instance
125
+ * @memberof Color
126
+ * @return {number} A value between 0.0 and 1.0.
127
+ */
128
+ red(): number {
129
+ return this.r;
130
+ }
131
+
132
+ /**
133
+ * Get the green component of this RGB(A) color. This method just returns the `g` color attribute.
134
+ *
135
+ * @method green
136
+ * @instance
137
+ * @memberof Color
138
+ * @return {number} A value between 0.0 and 1.0.
139
+ */
140
+ green(): number {
141
+ return this.g;
142
+ }
143
+
144
+ /**
145
+ * Get the blue component of this RGB(A) color. This method just returns the `b` color attribute.
146
+ *
147
+ * @method blue
148
+ * @instance
149
+ * @memberof Color
150
+ * @return {number} A value between 0.0 and 1.0.
151
+ */
152
+ blue(): number {
153
+ return this.b;
154
+ }
155
+
156
+ setRed(r: number) {
157
+ this.r = r;
158
+ return this;
159
+ }
160
+
161
+ setBlue(b: number) {
162
+ this.b = b;
163
+ Color.Converter.RGBToHSL(this);
164
+ return this;
165
+ }
166
+
167
+ setAlpha(a: number) {
168
+ this.a = a;
169
+ Color.Converter.RGBToHSL(this);
170
+ return this;
171
+ }
172
+
173
+ setGreen(g: number) {
174
+ this.g = g;
175
+ Color.Converter.RGBToHSL(this);
176
+ return this;
177
+ }
178
+
179
+ setHue(h: number) {
180
+ this.h = h;
181
+ Color.Converter.HSLToRGB(this);
182
+ return this;
183
+ }
184
+
185
+ setSaturation(s: number) {
186
+ this.s = s;
187
+ Color.Converter.HSLToRGB(this);
188
+ return this;
189
+ }
190
+
191
+ setLuminance(l: number) {
192
+ this.l = l;
193
+ Color.Converter.HSLToRGB(this);
194
+ return this;
195
+ }
196
+
197
+ // --- HSL ----------------------------------
198
+ /**
199
+ * Get this color as a CSS `hsl` string.
200
+ *
201
+ * @method cssHSL
202
+ * @instance
203
+ * @memberof Color
204
+ * @return {string} This color as a CSS hsl string.
205
+ */
206
+ cssHSL(): string {
207
+ return "hsl(" + Math.round(360 * this.h) + "," + Math.round(100 * this.s) + "%," + Math.round(100 * this.l) + "%)";
208
+ }
209
+
210
+ /**
211
+ * Get this color as a CSS `hsla` string.
212
+ *
213
+ * @method cssHSLA
214
+ * @instance
215
+ * @memberof Color
216
+ * @return {string} This color as a CSS hsla string.
217
+ */
218
+ cssHSLA(): string {
219
+ return (
220
+ "hsla(" +
221
+ Math.round(360 * this.h) +
222
+ "," +
223
+ Math.round(100 * this.s) +
224
+ "%," +
225
+ Math.round(100 * this.l) +
226
+ "%," +
227
+ Math.round(this.a) +
228
+ ")"
229
+ );
230
+ }
231
+
232
+ /**
233
+ * Get the hue component of this HSL(A) color. This method just returns the `h` color attribute.
234
+ *
235
+ * @method hue
236
+ * @instance
237
+ * @memberof Color
238
+ * @return {number} A value between 0.0 and 1.0.
239
+ */
240
+ hue(): number {
241
+ return this.h;
242
+ }
243
+
244
+ /**
245
+ * Get the saturation component of this HSL(A) color. This method just returns the `s` color attribute.
246
+ *
247
+ * @method saturation
248
+ * @instance
249
+ * @memberof Color
250
+ * @return {number} A value between 0.0 and 1.0.
251
+ */
252
+ saturation(): number {
253
+ return this.s;
254
+ }
255
+
256
+ /**
257
+ * Get the lightness component of this HSL(A) color. This method just returns the `l` color attribute.
258
+ *
259
+ * @method lightness
260
+ * @instance
261
+ * @memberof Color
262
+ * @return {number} A value between 0.0 and 1.0.
263
+ */
264
+ lightness(): number {
265
+ return this.l;
266
+ }
267
+
268
+ // --- HEX ----------------------------------
269
+ /**
270
+ * Get this color as a CSS-HEX string (non-alpha): #rrggbb
271
+ *
272
+ * @method cssHEX
273
+ * @instance
274
+ * @memberof Color
275
+ * @return {string} This color as a CSS-HEX string.
276
+ */
277
+ cssHEX(): string {
278
+ return (
279
+ "#" +
280
+ (255 * this.r < 16 ? "0" : "") +
281
+ Math.round(255 * this.r).toString(16) +
282
+ (255 * this.g < 16 ? "0" : "") +
283
+ Math.round(255 * this.g).toString(16) +
284
+ (255 * this.b < 16 ? "0" : "") +
285
+ Math.round(255 * this.b).toString(16)
286
+ );
287
+ }
288
+
289
+ // --- Transparency ----------------------------------
290
+
291
+ /**
292
+ * Get the alpha channel (transparency) of this color.
293
+ *
294
+ * @method alpha
295
+ * @instance
296
+ * @memberof Color
297
+ * @return {number} A value between 0.0 and 1.0.
298
+ */
299
+ alpha(): number {
300
+ return this.a;
301
+ }
302
+
303
+ // --- Modifiers ----------------------------------
304
+
305
+ // saturate(v: string | number): Color {
306
+ // if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
307
+ // this.s += v / 100;
308
+ // } else if ("number" == typeof v) {
309
+ // // range 255
310
+ // this.s += v / 255;
311
+ // } else {
312
+ // throw new Error("error: bad modifier format (percent or number)");
313
+ // }
314
+ // if (this.s > 1) this.s = 1;
315
+ // else if (this.s < 0) this.s = 0;
316
+ // Color.Converter.HSLToRGB(this);
317
+ // return this;
318
+ // }
319
+ saturate(v: string | number): Color {
320
+ if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
321
+ this.s += (1 - this.s) * (v / 100);
322
+ } else if ("number" == typeof v) {
323
+ if (v >= -0.0 && v <= 1.0) {
324
+ // range 255
325
+ this.s += (1 - this.s) * v;
326
+ } else {
327
+ // range 0-1
328
+ this.s += (1 - this.s) * (v / 255);
329
+ }
330
+ } else {
331
+ throw new Error("error: bad modifier format (percent or number)");
332
+ }
333
+ if (this.s > 1) this.s = 1;
334
+ else if (this.s < 0) this.s = 0;
335
+ Color.Converter.HSLToRGB(this);
336
+ return this;
337
+ }
338
+ desaturate(v: string | number): Color {
339
+ if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
340
+ this.s -= v / 100;
341
+ } else if ("number" == typeof v) {
342
+ if (v >= 0.0 && v <= 1.0) {
343
+ // range 255
344
+ this.s -= this.s * v;
345
+ } else {
346
+ // range 0-1
347
+ this.s -= this.s * (v / 255);
348
+ }
349
+ } else {
350
+ throw new Error("error: bad modifier format (percent or number)");
351
+ }
352
+ if (this.s > 1) this.s = 1;
353
+ else if (this.s < 0) this.s = 0;
354
+ Color.Converter.HSLToRGB(this);
355
+ return this;
356
+ }
357
+ // lighten(v: string | number): Color {
358
+ // if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
359
+ // this.l += v / 100;
360
+ // } else if ("number" == typeof v) {
361
+ // if (v >= -1.0 && v <= 1.0) {
362
+ // // range 0.0...1.0
363
+ // this.l += v;
364
+ // } else {
365
+ // // range 255
366
+ // this.l += v / 255;
367
+ // }
368
+ // } else {
369
+ // throw new Error("error: bad modifier format (percent or number)");
370
+ // }
371
+ // if (this.l > 1) this.l = 1;
372
+ // else if (this.l < 0) this.l = 0;
373
+ // Color.Converter.HSLToRGB(this);
374
+ // return this;
375
+ // }
376
+ lighten(v: string | number): Color {
377
+ if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
378
+ this.l += (1 - this.l) * (v / 100);
379
+ } else if ("number" == typeof v) {
380
+ if (v >= 0.0 && v <= 1.0) {
381
+ // range 0.0...1.0
382
+ this.l += (1 - this.l) * v;
383
+ } else {
384
+ // range 255
385
+ this.l += (1 - this.l) * (v / 255);
386
+ }
387
+ } else {
388
+ throw new Error("error: bad modifier format (percent or number)");
389
+ }
390
+ if (this.l > 1) this.l = 1;
391
+ else if (this.l < 0) this.l = 0;
392
+ Color.Converter.HSLToRGB(this);
393
+ return this;
394
+ }
395
+ darken(v: string | number): Color {
396
+ if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
397
+ this.l -= this.l * (v / 100);
398
+ } else if ("number" == typeof v) {
399
+ if (v >= 0.0 && v <= 1.0) {
400
+ // range 0.0...1.0
401
+ this.l -= this.l * v;
402
+ } else {
403
+ // range 255
404
+ this.l -= this.l * (v / 255);
405
+ }
406
+ } else {
407
+ throw new Error("error: bad modifier format (percent or number)");
408
+ }
409
+ if (this.l > 1) this.l = 1;
410
+ else if (this.l < 0) this.l = 0;
411
+ Color.Converter.HSLToRGB(this);
412
+ return this;
413
+ }
414
+ fadein(v: string | number): Color {
415
+ if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
416
+ this.a += (1 - this.a) * (v / 100);
417
+ } else if ("number" == typeof v) {
418
+ if (v >= 0.0 && v <= 1.0) {
419
+ // range 0-1
420
+ this.a += (1 - this.a) * v;
421
+ } else {
422
+ // range 255
423
+ this.a += (1 - this.a) * (v / 255);
424
+ }
425
+ } else {
426
+ throw new Error("error: bad modifier format (percent or number)");
427
+ }
428
+ console.log("New alpha", this.a);
429
+ if (this.a > 1) this.a = 1;
430
+ else if (this.a < 0) this.a = 0;
431
+ Color.Converter.HSLToRGB(this);
432
+ return this;
433
+ }
434
+ fadeout(v: string | number): Color {
435
+ if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) {
436
+ this.a -= v / 100;
437
+ } else if ("number" == typeof v) {
438
+ if (v >= 0.0 && v <= 1.0) {
439
+ // range 0-1
440
+ this.a -= v;
441
+ } else {
442
+ // range 255
443
+ this.a -= v / 255;
444
+ }
445
+ } else {
446
+ throw new Error("error: bad modifier format (percent or number)");
447
+ }
448
+ if (this.a > 1) this.a = 1;
449
+ else if (this.a < 0) this.a = 0;
450
+ Color.Converter.HSLToRGB(this);
451
+ return this;
452
+ }
453
+ spin(v: string | number): Color {
454
+ if ("string" == typeof v && v.indexOf("%") > -1 && (v = parseInt(v)) != NaN) this.h += v / 100;
455
+ else if ("number" == typeof v)
456
+ // range 360
457
+ this.h += v / 360;
458
+ else throw new Error("error: bad modifier format (percent or number)");
459
+ if (this.h > 1) this.h = 1;
460
+ else if (this.h < 0) this.h = 0;
461
+ Color.Converter.HSLToRGB(this);
462
+ return this;
463
+ }
464
+
465
+ static makeRGB(...args: any[]): Color {
466
+ const c: Color = new Color();
467
+ let sanitized: Array<number>;
468
+ if (arguments.length < 3 || arguments.length > 4) throw new Error("error: 3 or 4 arguments");
469
+ sanitized = Color.Sanitizer.RGB(arguments[0], arguments[1], arguments[2]);
470
+ c.r = sanitized[0];
471
+ c.g = sanitized[1];
472
+ c.b = sanitized[2];
473
+ if (arguments.length == 4) {
474
+ c.a = arguments[3];
475
+ } else {
476
+ c.a = 1.0;
477
+ }
478
+ Color.Converter.RGBToHSL(c);
479
+ return c;
480
+ }
481
+
482
+ static makeHSL(...args: Array<number | string>): Color {
483
+ const c: Color = new Color();
484
+ let sanitized: Array<number>;
485
+ if (arguments.length < 3 || arguments.length > 4) throw new Error("error: 3 or 4 arguments");
486
+ sanitized = Color.Sanitizer.HSL(arguments[0], arguments[1], arguments[2]);
487
+ c.h = sanitized[0];
488
+ c.s = sanitized[1];
489
+ c.l = sanitized[2];
490
+ if (arguments.length == 4) c.a = arguments[3];
491
+ else c.a = 1.0;
492
+ Color.Converter.HSLToRGB(c);
493
+ return c;
494
+ }
495
+
496
+ static makeHEX(value: string): Color {
497
+ var c = new Color(),
498
+ sanitized;
499
+ // Edit Ika 2018-0308
500
+ // Allow leading '#'
501
+ if (value && value.startsWith("#")) value = value.substr(1);
502
+ Color.Validator.checkHEX(value);
503
+ if (value.length == 3) {
504
+ sanitized = Color.Sanitizer.RGB(
505
+ parseInt(value.substr(0, 1) + value.substr(0, 1), 16),
506
+ parseInt(value.substr(1, 1) + value.substr(1, 1), 16),
507
+ parseInt(value.substr(2, 1) + value.substr(2, 1), 16)
508
+ );
509
+ } else if (value.length == 6) {
510
+ sanitized = Color.Sanitizer.RGB(
511
+ parseInt(value.substr(0, 2), 16),
512
+ parseInt(value.substr(2, 2), 16),
513
+ parseInt(value.substr(4, 2), 16)
514
+ );
515
+ } else throw new Error("error: 3 or 6 arguments");
516
+ c.r = sanitized[0];
517
+ c.g = sanitized[1];
518
+ c.b = sanitized[2];
519
+ c.a = 1.0; // TODO: Accept #xxxxxxxx (8 chars, too, for alpha)
520
+ Color.Converter.RGBToHSL(c);
521
+ return c;
522
+ }
523
+
524
+ /**
525
+ * Parse the given color string. Currently only these formate are recognized: hex, rgb, rgba.
526
+ *
527
+ * @method parse
528
+ * @static
529
+ * @memberof Color
530
+ * @param {string} str - The string representation to parse.
531
+ * @return {Color} The color instance that's represented by the given string.
532
+ */
533
+ static parse(str: string): Color {
534
+ if (typeof str == "undefined") return null;
535
+ if ((str = str.trim().toLowerCase()).length == 0) return null;
536
+ if (str.startsWith("#")) return Color.makeHEX(str.substring(1, str.length));
537
+ if (str.startsWith("rgb")) {
538
+ var parts = str.match(/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,?\s*(\d*(?:\.\d+\s*)?)\)$/);
539
+ if (!parts) {
540
+ throw "Unrecognized color format (2): " + str;
541
+ }
542
+ // [ str, r, g, b, a|undefined ]
543
+ // console.log("parts", parts);
544
+ if (parts.length <= 4 || typeof parts[4] == "undefined" || parts[4] == "") {
545
+ return Color.makeRGB(parts[1], parts[2], parts[3]);
546
+ } else {
547
+ return Color.makeRGB(parts[1], parts[2], parts[3], Number(parts[4]));
548
+ }
549
+ } else {
550
+ throw "Unrecognized color format (1): " + str;
551
+ }
552
+ }
553
+
554
+ private static Sanitizer = {
555
+ RGB: function (...args: any[]) {
556
+ var o = [];
557
+ if (arguments.length == 0) {
558
+ return [];
559
+ }
560
+ // const allAreFrac = Color.testFrac( arguments );
561
+ for (var i = 0; i < arguments.length; i++) {
562
+ var c = arguments[i];
563
+ if ("string" == typeof c && c.indexOf("%") > -1) {
564
+ if ((c = parseInt(c)) == NaN) throw new Error("Bad format");
565
+ if (c < 0 || c > 100) throw new Error("Bad format");
566
+ o[i] = c / 100;
567
+ } else {
568
+ if ("string" == typeof c && (c = parseInt(c)) == NaN) {
569
+ throw new Error("Bad format");
570
+ }
571
+ if (c < 0) {
572
+ throw new Error("Bad format");
573
+ }
574
+ //else if( allAreFrac ) o[i] = c; // c >= 0 && c <= 1 (all)
575
+ else if (c >= 0 && c < 1) {
576
+ o[i] = c;
577
+ }
578
+ // else if(c >= 0.0 && c <= 1.0) o[i] = c;
579
+ else if (c >= 1 && c < 256) {
580
+ o[i] = c / 255;
581
+ }
582
+ // ???
583
+ // else if(c >= 0 && c < 256) o[i] = c/255;
584
+ else throw new Error("Bad format (" + c + ")");
585
+ }
586
+ }
587
+ return o;
588
+ },
589
+
590
+ HSL: function (...args: Array<string | number>): Array<number> {
591
+ if (arguments.length < 3 || arguments.length > 4) throw new Error("3 or 4 arguments required");
592
+ var h = arguments[0],
593
+ s = arguments[1],
594
+ l = arguments[2];
595
+ if ("string" == typeof h && (h = parseFloat(h)) == NaN) throw new Error("Bad format for hue");
596
+ if (h < 0 || h > 360) throw new Error("Hue out of range (0..360)");
597
+ else if ((("" + h).indexOf(".") > -1 && h > 1) || ("" + h).indexOf(".") == -1) h /= 360;
598
+ if ("string" == typeof s && s.indexOf("%") > -1) {
599
+ if ((s = parseInt(s)) == NaN) throw new Error("Bad format for saturation");
600
+ if (s < 0 || s > 100) throw new Error("Bad format for saturation");
601
+ s /= 100;
602
+ } else if (s < 0 || s > 1) throw new Error("Bad format for saturation");
603
+ if ("string" == typeof l && l.indexOf("%") > -1) {
604
+ if ((l = parseInt(l)) == NaN) throw new Error("Bad format for lightness");
605
+ if (l < 0 || l > 100) throw new Error("Bad format for lightness");
606
+ l /= 100;
607
+ } else if (l < 0 || l > 1) throw new Error("Bad format for lightness");
608
+ return [h, s, l];
609
+ }
610
+ }; // ENd sanitizer
611
+
612
+ private static Validator = {
340
613
  /**
341
- * Parse the given color string. Currently only these formate are recognized: hex, rgb, rgba.
342
- *
343
- * @method parse
344
- * @static
345
- * @memberof Color
346
- * @param {string} str - The string representation to parse.
347
- * @return {Color} The color instance that's represented by the given string.
614
+ * Check a hexa color (without #)
348
615
  */
349
- static parse( str:string ) : Color {
350
- if( typeof str == 'undefined' )
351
- return null;
352
- if( (str = str.trim().toLowerCase()).length == 0 )
353
- return null;
354
- if( str.startsWith('#') )
355
- return Color.makeHEX(str.substring(1,str.length));
356
- if( str.startsWith('rgb') ) {
357
- var parts = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(0\.\d+))?\)$/.exec(str);
358
- // [ str, r, g, b, a|undefined ]
359
- if( typeof parts[4] == 'undefined' )
360
- return Color.makeRGB(parts[1],parts[2],parts[3]);
361
- else
362
- return Color.makeRGB(parts[1],parts[2],parts[3],parts[4]);
363
- }
364
- else
365
- throw "Unrecognized color format: " + str;
366
- };
367
-
368
- private static Sanitizer = {
369
- RGB: function(...args: any[]) {
370
- var o = [];
371
- if(arguments.length == 0) {
372
- return [];
373
- }
374
- // const allAreFrac = Color.testFrac( arguments );
375
- for(var i = 0 ; i < arguments.length ; i++) {
376
- var c = arguments[i];
377
- if("string" == typeof c && c.indexOf("%") > -1) {
378
- if((c = parseInt(c)) == NaN)
379
- throw new Error("Bad format");
380
- if(c < 0 || c > 100)
381
- throw new Error("Bad format");
382
- o[i] = c/100;
383
- } else {
384
- // console.log( 'allAreFrac', allAreFrac, arguments );
385
- if("string" == typeof c && (c = parseInt(c)) == NaN) throw new Error("Bad format");
386
- if(c < 0) throw new Error("Bad format");
387
- //else if( allAreFrac ) o[i] = c; // c >= 0 && c <= 1 (all)
388
- else if(c >= 0 && c < 1) o[i] = c;
389
- // else if(c >= 0.0 && c <= 1.0) o[i] = c;
390
- else if(c >= 1 && c < 256) o[i] = c/255; // ???
391
- // else if(c >= 0 && c < 256) o[i] = c/255;
392
- else throw new Error("Bad format ("+c+")");
393
- }
394
- }
395
- return o;
396
- },
397
-
398
- HSL: function(...args: Array<string|number>) : Array<number> {
399
- if(arguments.length < 3 || arguments.length > 4) throw new Error("3 or 4 arguments required");
400
- var h = arguments[0],
401
- s = arguments[1],
402
- l = arguments[2];
403
- if("string" == typeof h && (h = parseFloat(h)) == NaN) throw new Error("Bad format for hue");
404
- if(h < 0 || h > 360) throw new Error("Hue out of range (0..360)");
405
- else if(((""+h).indexOf(".") > -1 && h > 1) || (""+h).indexOf(".") == -1) h /= 360;
406
- if("string" == typeof s && s.indexOf("%") > -1) {
407
- if((s = parseInt(s)) == NaN)
408
- throw new Error("Bad format for saturation");
409
- if(s < 0 || s > 100)
410
- throw new Error("Bad format for saturation");
411
- s /= 100;
412
- } else if(s < 0 || s > 1) throw new Error("Bad format for saturation");
413
- if("string" == typeof l && l.indexOf("%") > -1) {
414
- if((l = parseInt(l)) == NaN)
415
- throw new Error("Bad format for lightness");
416
- if(l < 0 || l > 100)
417
- throw new Error("Bad format for lightness");
418
- l /= 100;
419
- } else if(l < 0 || l > 1) throw new Error("Bad format for lightness");
420
- return [h, s, l];
421
- }
422
- }; // ENd sanitizer
423
-
424
- private static Validator = {
425
-
426
- /**
427
- * Check a hexa color (without #)
428
- */
429
- checkHEX: (value:string) => {
430
-
431
- if(value.length != 6 && value.length != 3)
432
- throw new Error("Hexa color: bad length ("+value.length+")," + value);
433
- value = value.toLowerCase();
434
- //for( var i in value ) {
435
- for( var i = 0; i < value.length; i++ ) {
436
- var c : number = value.charCodeAt(i);
437
- if( !((c>=48 && c<=57) || (c>=97 && c<=102)) )
438
- throw new Error(`Hexa color: out of range for "${value}" at position ${i}.`);
439
- }
440
- }
441
- };
442
-
443
- private static Converter = {
444
-
445
- /**
446
- * Calculates HSL Color.
447
- * RGB must be normalized.
448
- * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
449
- */
450
- RGBToHSL: (color:Color) => {
451
- var r : number = color.r;
452
- var g : number = color.g;
453
- var b : number = color.b;
454
- var max : number = Math.max(r, g, b);
455
- var min : number = Math.min(r, g, b);
456
- color.l = (max + min) / 2;
457
- if(max == min){
458
- color.h = color.s = 0; // achromatic
459
- } else {
460
- var d : number = max - min;
461
- color.s = color.l > 0.5 ? d / (2 - max - min) : d / (max + min);
462
- switch(max){
463
- case r: color.h = (g - b) / d + (g < b ? 6 : 0); break;
464
- case g: color.h = (b - r) / d + 2; break;
465
- case b: color.h = (r - g) / d + 4; break;
466
- }
467
- color.h /= 6;
468
- }
469
- },
470
-
471
- /**
472
- * Calculates RGB color (nomalized).
473
- * HSL must be normalized.
474
- *
475
- * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
476
- */
477
- HSLToRGB: (color:Color) => {
478
- var h : number = color.h;
479
- var s : number = color.s;
480
- var l : number = color.l;
481
- if(s == 0) {
482
- color.r = color.g = color.b = l; // achromatic
483
- } else {
484
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
485
- var p = 2 * l - q;
486
- color.r = Color.Converter.hue2rgb(p, q, h + 1/3);
487
- color.g = Color.Converter.hue2rgb(p, q, h);
488
- color.b = Color.Converter.hue2rgb(p, q, h - 1/3);
489
- }
490
- },
491
-
492
- hue2rgb : (p:number, q:number, t:number) : number => {
493
- if(t < 0) t += 1;
494
- if(t > 1) t -= 1;
495
- if(t < 1/6) return p + (q - p) * 6 * t;
496
- if(t < 1/2) return q;
497
- if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
498
- return p;
499
- }
500
-
501
- };
502
-
616
+ checkHEX: (value: string) => {
617
+ if (value.length != 6 && value.length != 3) throw new Error("Hexa color: bad length (" + value.length + ")," + value);
618
+ value = value.toLowerCase();
619
+ //for( var i in value ) {
620
+ for (var i = 0; i < value.length; i++) {
621
+ var c: number = value.charCodeAt(i);
622
+ if (!((c >= 48 && c <= 57) || (c >= 97 && c <= 102)))
623
+ throw new Error(`Hexa color: out of range for "${value}" at position ${i}.`);
624
+ }
625
+ }
626
+ };
627
+
628
+ private static Converter = {
503
629
  /**
504
- * Create a clone of this color (RGB).
505
- *
506
- * @method clone
507
- * @instance
508
- * @memberof Color
509
- * @return {Color} A clone of this color (in RGB mode).
630
+ * Calculates HSL Color.
631
+ * RGB must be normalized.
632
+ * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
510
633
  */
511
- clone() : Color {
512
- return Color.makeRGB(this.r, this.g, this.b, this.a);
513
- };
634
+ RGBToHSL: (color: Color) => {
635
+ var r: number = color.r;
636
+ var g: number = color.g;
637
+ var b: number = color.b;
638
+ var max: number = Math.max(r, g, b);
639
+ var min: number = Math.min(r, g, b);
640
+ color.l = (max + min) / 2;
641
+ if (max == min) {
642
+ color.h = color.s = 0; // achromatic
643
+ } else {
644
+ var d: number = max - min;
645
+ color.s = color.l > 0.5 ? d / (2 - max - min) : d / (max + min);
646
+ switch (max) {
647
+ case r:
648
+ color.h = (g - b) / d + (g < b ? 6 : 0);
649
+ break;
650
+ case g:
651
+ color.h = (b - r) / d + 2;
652
+ break;
653
+ case b:
654
+ color.h = (r - g) / d + 4;
655
+ break;
656
+ }
657
+ color.h /= 6;
658
+ }
659
+ },
514
660
 
515
-
516
661
  /**
517
- * Interpolate this color on the RGB scale.
662
+ * Calculates RGB color (nomalized).
663
+ * HSL must be normalized.
518
664
  *
519
- * @method interpolate
520
- * @instance
521
- * @memberof Color
522
- * @param {Color} c - The color to interpolate to.
523
- * @param {number} t - An interpolation value between 0.0 and 1.0.
524
- * @return {Color} A clone of this color (in RGB mode).
665
+ * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
525
666
  */
526
- interpolate( c:Color, t:number ) : Color {
527
- this.r += (c.r-c.r)*t;
528
- this.g += (c.g-c.g)*t;
529
- this.b += (c.b-c.b)*t;
530
- this.a += (c.a-c.a)*t;
531
- return this;
532
- };
533
-
534
- }; // END class
667
+ HSLToRGB: (color: Color) => {
668
+ var h: number = color.h;
669
+ var s: number = color.s;
670
+ var l: number = color.l;
671
+ if (s == 0) {
672
+ color.r = color.g = color.b = l; // achromatic
673
+ } else {
674
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
675
+ var p = 2 * l - q;
676
+ color.r = Color.Converter.hue2rgb(p, q, h + 1 / 3);
677
+ color.g = Color.Converter.hue2rgb(p, q, h);
678
+ color.b = Color.Converter.hue2rgb(p, q, h - 1 / 3);
679
+ }
680
+ },
681
+
682
+ hue2rgb: (p: number, q: number, t: number): number => {
683
+ if (t < 0) t += 1;
684
+ if (t > 1) t -= 1;
685
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
686
+ if (t < 1 / 2) return q;
687
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
688
+ return p;
689
+ }
690
+ };
691
+
692
+ /**
693
+ * Create a clone of this color (RGB).
694
+ *
695
+ * @method clone
696
+ * @instance
697
+ * @memberof Color
698
+ * @return {Color} A clone of this color (in RGB mode).
699
+ */
700
+ clone(): Color {
701
+ return Color.makeRGB(this.r, this.g, this.b, this.a);
702
+ }
703
+
704
+ /**
705
+ * Interpolate this color on the RGB scale.
706
+ *
707
+ * @method interpolate
708
+ * @instance
709
+ * @memberof Color
710
+ * @param {Color} c - The color to interpolate to.
711
+ * @param {number} t - An interpolation value between 0.0 and 1.0.
712
+ * @return {Color} A clone of this color (in RGB mode).
713
+ */
714
+ interpolate(c: Color, t: number): Color {
715
+ this.r += (c.r - c.r) * t;
716
+ this.g += (c.g - c.g) * t;
717
+ this.b += (c.b - c.b) * t;
718
+ this.a += (c.a - c.a) * t;
719
+ return this;
720
+ }
721
+ } // END class