221 lines
4.0 KiB
TypeScript
221 lines
4.0 KiB
TypeScript
import { HTMLColor } from './HTMLColor';
|
|
import { HSLColor } from './HSLColor';
|
|
|
|
export class RGBColor extends HTMLColor
|
|
{
|
|
private _r = 0;
|
|
get r(){ return this._r}
|
|
set r( value:number )
|
|
{
|
|
this._r = value;
|
|
}
|
|
|
|
private _g = 0;
|
|
get g(){ return this._g}
|
|
set g( value:number )
|
|
{
|
|
this._g = value;
|
|
}
|
|
|
|
private _b = 0;
|
|
get b(){ return this._b}
|
|
set b( value:number )
|
|
{
|
|
this._b = value;
|
|
}
|
|
|
|
constructor( r:number, g:number, b:number, a:number=1 )
|
|
{
|
|
super();
|
|
|
|
this._r = r;
|
|
this._g = g;
|
|
this._b = b;
|
|
this._a = a;
|
|
}
|
|
|
|
clone()
|
|
{
|
|
return new RGBColor( this.r, this.g, this.b, this.a );
|
|
}
|
|
|
|
copyFrom( other:HTMLColor )
|
|
{
|
|
if ( this === other )
|
|
{
|
|
return;
|
|
}
|
|
|
|
let otherInRGB = other.toRGB();
|
|
|
|
this._r = otherInRGB.r;
|
|
this._g = otherInRGB.g;
|
|
this._b = otherInRGB.b;
|
|
this._a = otherInRGB.a;
|
|
}
|
|
|
|
toRGB():RGBColor
|
|
{
|
|
return this;
|
|
}
|
|
|
|
toHSL():HSLColor
|
|
{
|
|
return HSLColor.fromRGBColor( this );
|
|
}
|
|
|
|
get r255()
|
|
{
|
|
return Math.round( this._r * 255 );
|
|
}
|
|
|
|
get g255()
|
|
{
|
|
return Math.round( this._g * 255 );
|
|
}
|
|
|
|
get b255()
|
|
{
|
|
return Math.round( this._b * 255 );
|
|
}
|
|
|
|
toString():string
|
|
{
|
|
return `rgba(${this.r255},${this.g255},${this.b255},${this._a})`;
|
|
}
|
|
|
|
scaleRGB( scalar:number )
|
|
{
|
|
this.r *= scalar;
|
|
this.g *= scalar;
|
|
this.b *= scalar;
|
|
}
|
|
|
|
getEuclideanDistance( color:HTMLColor )
|
|
{
|
|
let rgb = color.toRGB();
|
|
|
|
let rDiff = rgb.r - this.r;
|
|
let gDiff = rgb.g - this.g;
|
|
let bDiff = rgb.b - this.b;
|
|
let aDiff = rgb.a - this.a;
|
|
|
|
return Math.sqrt( rDiff * rDiff + gDiff * gDiff + bDiff * bDiff + aDiff * aDiff );
|
|
}
|
|
|
|
static lerp( colorA:HTMLColor, colorB:HTMLColor, lerp:number ):RGBColor
|
|
{
|
|
let A = colorA.toRGB();
|
|
let B = colorB.toRGB();
|
|
|
|
let inverseLerp = 1 - lerp;
|
|
|
|
let r = A.r * inverseLerp + B.r * lerp;
|
|
let g = A.g * inverseLerp + B.g * lerp;
|
|
let b = A.b * inverseLerp + B.b * lerp;
|
|
let a = A.a * inverseLerp + B.a * lerp;
|
|
|
|
return new RGBColor( r, g, b, a );
|
|
}
|
|
|
|
static lerpFrom( colors:HTMLColor[], lerp:number ):RGBColor
|
|
{
|
|
if ( lerp <= 0 )
|
|
{
|
|
return colors[ 0 ].toRGB();
|
|
}
|
|
|
|
if ( lerp >= 1 )
|
|
{
|
|
return colors[ colors.length - 1 ].toRGB();
|
|
}
|
|
|
|
let index = lerp * ( colors.length - 1 );
|
|
let floored = Math.floor( index );
|
|
|
|
let amount = index - floored;
|
|
|
|
|
|
let colorA = colors[ floored ];
|
|
let colorB = colors[ floored + 1 ];
|
|
|
|
return RGBColor.lerp( colorA, colorB, amount );
|
|
}
|
|
|
|
equals( other:HTMLColor )
|
|
{
|
|
if ( ! other )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
let otherRGB = other.toRGB();
|
|
|
|
if ( otherRGB.r !== this.r )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( otherRGB.g !== this.g )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( otherRGB.b !== this.b )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( otherRGB.a !== this.a )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
static fromString( colorString:string )
|
|
{
|
|
colorString = colorString.trim();
|
|
|
|
let rgbStart = /rgba?\(/;
|
|
|
|
if ( ! rgbStart.test( colorString ) )
|
|
{
|
|
console.error( "Does not start with", rgbStart, " ==> '" + colorString + "'" );
|
|
return null;
|
|
}
|
|
|
|
colorString = colorString.replace( rgbStart, "" );
|
|
colorString = colorString.replace( /\)$/, "" );
|
|
|
|
let numbers = JSON.parse( "[" + colorString + "]" ) as number[];
|
|
|
|
if ( ! Array.isArray( numbers ) )
|
|
{
|
|
console.error( "Is not a list of numbers", " ==> '" + colorString + "'" );
|
|
return null;
|
|
}
|
|
|
|
let notNumeric = numbers.findIndex( n => typeof n !== "number" );
|
|
|
|
if ( notNumeric !== -1 )
|
|
{
|
|
console.error( "Found a not-numeric at index:", notNumeric, " ==> '" + colorString + "'" );
|
|
return null;
|
|
}
|
|
|
|
if ( ! ( numbers.length === 3 || numbers.length === 4 ) )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if ( numbers.length === 3 )
|
|
{
|
|
numbers.push( 1 );
|
|
}
|
|
|
|
return new RGBColor( numbers[ 0 ] / 255, numbers[ 1 ] / 255, numbers[ 2 ] / 255, numbers[ 3 ] );
|
|
}
|
|
} |