ambilighter
Version:
Ambilight around the video, image or canvas HTML elements
163 lines (91 loc) • 3.12 kB
text/typescript
import { IAmbilighter } from '../interfaces/ambilighter.interfaces';
import { IOptions } from '../interfaces/options.interfaces';
import { IOutput } from '../interfaces/output.interface.ts';
import { Ambilighter } from './ambilighter.ts';
import { averageColor, getImageData } from '../utils/adapters';
import { Vector } from '../types/vectors.types.ts';
export class AmbilighterImage extends Ambilighter< HTMLImageElement > implements IAmbilighter {
constructor ( el: ( HTMLImageElement | null ), options: IOptions ) {
super( el, options );
try {
if ( !( el instanceof HTMLImageElement ) ) {
throw new Error( 'AmbilighterImage -> constructor :: invalid element' );
}
el.onload = (): void => {
this.update();
}
this.update();
} catch ( e: unknown ) {
console.error( e );
}
return new Proxy( this, {
set( target: AmbilighterImage, prop: ( string | symbol ), handler: (..._args: any) => void ): boolean {
if ( prop === 'onUpdate' ) {
target[ prop ] = handler;
target.update();
}
return true;
},
} );
}
static override validate( el: ( HTMLElement | null ) ): boolean {
return el instanceof HTMLImageElement;
}
protected update (): void {
this.updateCanvas( this.el );
const output: IOutput = {
frame: {
top: {
color: averageColor( getImageData( this.canvas, Vector.top ) ),
radius: this.radius,
},
bottom: {
color: averageColor( getImageData( this.canvas, Vector.bottom ) ),
radius: this.radius,
},
left: {
color: averageColor( getImageData( this.canvas, Vector.left ) ),
radius: this.radius,
},
right: {
color: averageColor( getImageData( this.canvas, Vector.right ) ),
radius: this.radius,
},
},
averageColor: averageColor( getImageData( this.canvas, Vector.bottomRight ) ),
};
// Fires onLoad hook
this.onUpdate( output );
}
/**
* Updates when picture repainted
* @param image { any }
*/
protected override updateCanvas ( image: HTMLImageElement ): void {
try {
const ctx: ( CanvasRenderingContext2D | null ) = this.canvas.getContext( '2d' );
if ( ctx ) {
this.canvas.width = image.naturalWidth;
this.canvas.height = image.naturalHeight;
ctx.drawImage( image, 0, 0, image.naturalWidth, image.naturalHeight );
}
} catch ( e: unknown ) {
console.error( e );
}
}
/**
* getters / setters
*/
get radius (): number {
return this?.options?.radius || 0;
}
/**
* Hooks
*/
override onLoad ( ..._args: any ): void {
}
override onUpdate ( ..._args: any ): void {
}
override onDestroy(): void {
}
};