library-ts/browser/colors/RGBColor.ts

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 ] );
}
}