Files
Bubberstation/tgui/packages/common/color.ts
SkyratBot b215646850 [MIRROR] Tgui: Events & Colors in typescript (#27754)
* Tgui: Events & Colors in typescript (#83218)

## About The Pull Request
Made more common tgui bits in typescript with tests. Not much else to
see here
## Why It's Good For The Game
Typescript conversion + More documentation + type safety

You now get full docs and type info as nature intended:

![image](https://github.com/tgstation/tgstation/assets/42397676/17a7aad6-56d3-4e22-89fa-585cda4c5315)

---------

Co-authored-by: Style Mistake <stylemistake@ gmail.com>

* Tgui: Events & Colors in typescript

---------

Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
Co-authored-by: Style Mistake <stylemistake@ gmail.com>
2024-05-18 02:30:15 +02:00

95 lines
2.2 KiB
TypeScript

/**
* @file
* @copyright 2020 Aleksej Komarov
* @license MIT
*/
const EPSILON = 0.0001;
export class Color {
r: number;
g: number;
b: number;
a: number;
constructor(r = 0, g = 0, b = 0, a = 1) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
toString(): string {
// Alpha component needs to permit fractional values, so cannot use |
let alpha = this.a;
if (typeof alpha === 'string') {
alpha = parseFloat(this.a as any);
}
if (isNaN(alpha)) {
alpha = 1;
}
return `rgba(${this.r | 0}, ${this.g | 0}, ${this.b | 0}, ${alpha})`;
}
/** Darkens a color by a given percent. Returns a color, which can have toString called to get it's rgba() css value. */
darken(percent: number): Color {
percent /= 100;
return new Color(
this.r - this.r * percent,
this.g - this.g * percent,
this.b - this.b * percent,
this.a,
);
}
/** Brightens a color by a given percent. Returns a color, which can have toString called to get it's rgba() css value. */
lighten(percent: number): Color {
// No point in rewriting code we already have.
return this.darken(-percent);
}
/**
* Creates a color from the CSS hex color notation.
*/
static fromHex(hex: string): Color {
return new Color(
parseInt(hex.slice(1, 3), 16),
parseInt(hex.slice(3, 5), 16),
parseInt(hex.slice(5, 7), 16),
);
}
/**
* Linear interpolation of two colors.
*/
static lerp(c1: Color, c2: Color, n: number): Color {
return new Color(
(c2.r - c1.r) * n + c1.r,
(c2.g - c1.g) * n + c1.g,
(c2.b - c1.b) * n + c1.b,
(c2.a - c1.a) * n + c1.a,
);
}
/**
* Loops up the color in the provided list of colors
* with linear interpolation.
*/
static lookup(value: number, colors: Color[]): Color {
const len = colors.length;
if (len < 2) {
throw new Error('Needs at least two colors!');
}
const scaled = value * (len - 1);
if (value < EPSILON) {
return colors[0];
}
if (value >= 1 - EPSILON) {
return colors[len - 1];
}
const ratio = scaled % 1;
const index = scaled | 0;
return this.lerp(colors[index], colors[index + 1], ratio);
}
}