11import { AnimationAPI , AnimationFrame } from './Animation' ;
22import { useType } from '@hex-engine/core' ;
3- import gifken from 'gifken' ;
3+ import gifken , { Gif } from 'gifken' ;
44
5- interface GIFInterface extends AnimationAPI < { } > {
5+ interface GIFInterface extends AnimationAPI < HTMLImageElement > {
6+ getGif ( ) : Gif ,
67 drawCurrentFrame ( context : CanvasRenderingContext2D ) : void ;
78}
89
9- export default function GIF ( options : { url : string } ) : GIFInterface {
10+ export default function GIF ( options : { url : string , width : number , height : number , fps ?: number , compressed ?: boolean , loop ?: boolean } ) : GIFInterface {
1011 useType ( GIF ) ;
11- let frames : any [ ] = [ ] ;
12+ let gif : Gif = new Gif ( ) ;
13+ let frames : AnimationFrame < HTMLImageElement > [ ] = [ ] ;
14+ let play : boolean = false ;
1215 let i = 0 ;
1316
14- var xhr = new XMLHttpRequest ( ) ;
15- xhr . open ( "GET" , options . url , true ) ;
16- xhr . responseType = "arraybuffer" ;
17- xhr . onload = ( e : any ) => {
18- var arrayBuffer = e . target [ "response" ] ;
19- var gif = gifken . Gif . parse ( arrayBuffer ) ;
20-
21- frames = gif . split ( false ) . map ( frame => {
22- const url = URL . createObjectURL ( new Blob ( frame . writeToArrayBuffer ( ) ) ) . toString ( ) ;
23- const img = document . createElement ( 'img' ) ;
24- img . src = url ;
25- return img
17+ load ( options . url ) . then ( arrayBuffer => {
18+ gif = gifken . Gif . parse ( arrayBuffer ) ;
19+ frames = getFrames ( {
20+ gif,
21+ width : options . width ,
22+ height : options . height ,
23+ compressed : options . compressed
2624 } )
27- } ;
28- xhr . send ( ) ;
2925
26+ setInterval ( ( ) => {
27+ if ( frames . length - 1 > i && play ) {
28+ i ++ ;
29+ }
30+
31+ if ( frames . length - 1 <= i && options . loop && play ) {
32+ i = 0 ;
33+ }
34+ } , 30 )
35+ } )
36+
37+
3038 return {
39+ getGif ( ) {
40+ return gif ;
41+ } ,
3142 drawCurrentFrame ( context : CanvasRenderingContext2D ) {
32- if ( frames . length !== 0 ) {
33- context . drawImage ( frames [ i ] , 0 , 0 ) ;
34- if ( frames . length - 1 > i ) {
35- i ++ ;
36- }
43+ if ( frames . length !== 0 && play ) {
44+ context . drawImage ( frames [ i ] . data , 0 , 0 ) ;
3745 }
3846 } ,
39- frames : [ ] ,
40- loop : false ,
41- currentFrameIndex : 0 ,
42- currentFrame : new AnimationFrame ( { } , {
43- duration : 0 ,
44- } ) ,
47+ frames : frames ,
48+ loop : options . loop || false ,
49+ currentFrameIndex : i ,
50+ currentFrame : frames [ i ] ,
4551 currentFrameCompletion : 0 ,
4652 pause ( ) {
47- return void 0 ;
53+ play = false ;
4854 } ,
4955 resume ( ) {
50- return void 0 ;
56+ play = true ;
5157 } ,
5258 play ( ) {
53- return void 0 ;
59+ play = true ;
5460 } ,
5561 restart ( ) {
56- return void 0 ;
62+ i = 0 ;
63+ play = true ;
5764 } ,
5865 goToFrame ( frameNumber : number ) {
59- return frameNumber ;
66+ i = frameNumber ;
6067 } ,
6168 }
69+ }
70+
71+ async function load ( url : string ) {
72+ return await fetch ( url )
73+ . then ( ( res ) => res . arrayBuffer ( ) ) ;
74+ }
75+
76+ function getFrames ( { gif, width, height, compressed = false } : {
77+ gif : Gif ,
78+ width : number ,
79+ height : number ,
80+ compressed ?: boolean ,
81+ } ) {
82+ return gif . split ( compressed ) . map ( frame => {
83+ const blob = gifken . GifPresenter . writeToBlob ( frame . writeToArrayBuffer ( ) )
84+ const url = URL . createObjectURL ( blob ) . toString ( ) ;
85+ const img = document . createElement ( 'img' ) ;
86+ img . width = width ;
87+ img . height = height ;
88+ img . src = url ;
89+ return new AnimationFrame < HTMLImageElement > ( img , {
90+ duration : 0 ,
91+ } ) ;
92+ } ) ;
6293}
0 commit comments