class Moire implements Effect { private width : number ; private height : number ; public async init ( width , height ) { this . width = width ; this . height = height ; } public render ( ctx , t ) { const dest = ctx . getImageData ( 0 , 0 , this . width , this . height ) ; const time = t / 1000 ; const cx1 = Math . sin ( time / 2 ) * this . width / 3 + this . width / 2 ; const cy1 = Math . sin ( time / 4 ) * this . height / 3 + this . height / 2 ; const cx2 = Math . cos ( time / 3 ) * this . width / 3 + this . width / 2 ; const cy2 = Math . cos ( time ) * this . height / 3 + this . height / 2 ; let destOfs = 0 ; for ( let y = 0 ; y < this . height ; y ++ ) { const dy = ( y - cy1 ) * ( y - cy1 ) ; const dy2 = ( y - cy2 ) * ( y - cy2 ) ; for ( let x = 0 ; x < this . width ; x ++ ) { const dx = ( x - cx1 ) * ( x - cx1 ) ; const dx2 = ( x - cx2 ) * ( x - cx2 ) ; const shade = ( ( ( Math . sqrt ( dx + dy ) ^ Math . sqrt ( dx2 + dy2 ) ) >> 4 ) & 1 ) * 255 ; dest . data [ destOfs ++ ] = shade ; dest . data [ destOfs ++ ] = shade ; dest . data [ destOfs ++ ] = shade ; dest . data [ destOfs ++ ] = 0xff ; } } ctx . putImageData ( dest , 0 , 0 ) ; } } demoFX . register ( "moire" , new Moire ( ) ) ;