@@ -81,7 +81,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
8181
8282 private _boundOnScroll : ( ) => void ;
8383
84- constructor ( options : ScrollFrameCanvasOptions ) {
84+ constructor ( options : ScrollFrameCanvasOptions ) {
8585 super ( ) ;
8686 if ( ! options || ! options . canvasEle ) throw new Error ( 'canvasEle 必填' ) ;
8787 if ( ! options . scrollbarEle ) throw new Error ( 'scrollbarEle 必填' ) ;
@@ -148,7 +148,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
148148 }
149149
150150 /** 启动 */
151- async init ( ) : Promise < this> {
151+ async init ( ) : Promise < this> {
152152 const total = this . getTotalFrames ( ) ;
153153 this . _preRenderedFrames = new Array ( total ) ;
154154
@@ -245,7 +245,6 @@ export default class ScrollFrameCanvas extends EventEmitter {
245245 }
246246
247247
248-
249248 // 恢复滚动
250249 this . _enableScroll ( ) ;
251250
@@ -262,14 +261,14 @@ export default class ScrollFrameCanvas extends EventEmitter {
262261 }
263262
264263 /** 开始播放(启用渲染循环) */
265- play ( ) : void {
264+ play ( ) : void {
266265 if ( this . _playing ) return ;
267266 this . _playing = true ;
268267 this . _tick ( ) ;
269268 }
270269
271270 /** 暂停播放 */
272- pause ( ) : void {
271+ pause ( ) : void {
273272 this . _playing = false ;
274273 if ( this . _rAFId ) {
275274 cancelAnimationFrame ( this . _rAFId ) ;
@@ -278,32 +277,32 @@ export default class ScrollFrameCanvas extends EventEmitter {
278277 }
279278
280279 /** 停止并重置到 0 帧 */
281- stop ( ) : void {
280+ stop ( ) : void {
282281 this . pause ( ) ;
283282 this . setFrame ( 0 ) ;
284283 }
285284
286285 /**
287286 * 设置当前帧
288287 */
289- setFrame ( frameIndex : number ) : void {
288+ setFrame ( frameIndex : number ) : void {
290289 const idx = clamp ( Math . round ( frameIndex ) , 0 , this . getTotalFrames ( ) - 1 ) ;
291290 this . _currentFrame = idx ;
292291 this . _renderIfNeeded ( ) ;
293292 }
294293
295294 /** 获取当前帧索引 */
296- getCurrentFrame ( ) : number {
295+ getCurrentFrame ( ) : number {
297296 return this . _currentFrame ;
298297 }
299298
300299 /** 获取总帧数 */
301- getTotalFrames ( ) : number {
300+ getTotalFrames ( ) : number {
302301 return this . total ;
303302 }
304303
305304 /** 销毁并清理资源 */
306- destroy ( ) : void {
305+ destroy ( ) : void {
307306 if ( this . _destroyed ) return ;
308307 this . pause ( ) ;
309308 this . _detachScroll ( ) ;
@@ -328,7 +327,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
328327 this . _destroyed = true ;
329328 }
330329
331- private _cleanupNullFrames ( ) : void {
330+ private _cleanupNullFrames ( ) : void {
332331 // 移除 null 元素,重新排列数组
333332 const validFrames : ImageBitmap [ ] = [ ] ;
334333 const originalLength = this . _preRenderedFrames . length ;
@@ -354,6 +353,9 @@ export default class ScrollFrameCanvas extends EventEmitter {
354353 index : number , offscreenCanvas : OffscreenCanvas , offscreenCtx : OffscreenCanvasRenderingContext2D ,
355354 isBack = false ,
356355 ) : Promise < void > {
356+ if ( this . _destroyed ) {
357+ throw new Error ( 'ScrollFrameCanvas 已销毁' ) ;
358+ }
357359 try {
358360 const image = await this . _loadFrame ( index ) ;
359361
@@ -379,7 +381,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
379381 }
380382 }
381383
382- private async _parseImageData ( index : number , offscreenCanvas : OffscreenCanvas , offscreenCtx : OffscreenCanvasRenderingContext2D , image : ImageBitmap | HTMLImageElement ) : Promise < void > {
384+ private async _parseImageData ( index : number , offscreenCanvas : OffscreenCanvas , offscreenCtx : OffscreenCanvasRenderingContext2D , image : ImageBitmap | HTMLImageElement ) : Promise < void > {
383385 try {
384386 if ( image instanceof ImageBitmap ) {
385387 this . _preRenderedFrames [ index ] = image ;
@@ -399,7 +401,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
399401 }
400402 }
401403
402- private async _loadFrame ( index : number ) : Promise < HTMLImageElement | ImageBitmap | null > {
404+ private async _loadFrame ( index : number ) : Promise < HTMLImageElement | ImageBitmap | null > {
403405 const image = await this . _getImage ( index ) ;
404406 if ( image === null ) {
405407 return null ;
@@ -410,7 +412,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
410412 return image ;
411413 }
412414
413- private async _getImage ( index : number ) : Promise < HTMLImageElement | ImageBitmap | string | null > {
415+ private async _getImage ( index : number ) : Promise < HTMLImageElement | ImageBitmap | string | null > {
414416 if ( this . images ) {
415417 if ( this . images [ index ] === undefined ) {
416418 throw new Error ( `images 数组索引 ${ index } 对应的图片为 undefined` ) ;
@@ -429,7 +431,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
429431 return result ;
430432 }
431433
432- private _loadImageFromURL ( url : string ) : Promise < HTMLImageElement > {
434+ private _loadImageFromURL ( url : string ) : Promise < HTMLImageElement > {
433435 return new Promise ( ( resolve , reject ) => {
434436 const img = new Image ( ) ;
435437 img . crossOrigin = 'anonymous' ;
@@ -439,7 +441,8 @@ export default class ScrollFrameCanvas extends EventEmitter {
439441 } ) ;
440442 }
441443
442- private _drawImageToOffscreen ( img : HTMLImageElement | ImageBitmap , ctx : OffscreenCanvasRenderingContext2D , canvasW : number , canvasH : number ) : void {
444+ private _drawImageToOffscreen ( img : HTMLImageElement | ImageBitmap , ctx : OffscreenCanvasRenderingContext2D , canvasW : number , canvasH : number ) : void {
445+ if ( this . _destroyed ) return ;
443446 const natW = ( img as HTMLImageElement ) . naturalWidth || img . width || 1 ;
444447 const natH = ( img as HTMLImageElement ) . naturalHeight || img . height || 1 ;
445448
@@ -448,7 +451,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
448451 ctx . drawImage ( img , 0 , 0 , natW , natH , Math . round ( fit . x ) , Math . round ( fit . y ) , Math . round ( fit . w ) , Math . round ( fit . h ) ) ;
449452 }
450453
451- private _disableScroll ( ) : void {
454+ private _disableScroll ( ) : void {
452455 const el = this . scrollbarEle ;
453456 if ( el === window || el === document || el === document . body ) {
454457 // 保存原始滚动行为
@@ -474,7 +477,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
474477 }
475478 }
476479
477- private _enableScroll ( ) : void {
480+ private _enableScroll ( ) : void {
478481 const el = this . scrollbarEle ;
479482 if ( el === window || el === document || el === document . body ) {
480483 // 恢复原始滚动行为
@@ -489,7 +492,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
489492 }
490493 }
491494
492- private _attachScroll ( ) : void {
495+ private _attachScroll ( ) : void {
493496 const el = this . scrollbarEle ;
494497 if ( ! el ) return ;
495498 const opts = { passive : true } ;
@@ -502,7 +505,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
502505 }
503506 }
504507
505- private _detachScroll ( ) : void {
508+ private _detachScroll ( ) : void {
506509 const el = this . scrollbarEle ;
507510 if ( ! el ) return ;
508511 if ( el === window || el === document ) {
@@ -515,7 +518,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
515518 }
516519
517520
518- private _getScrollPixels ( ) : { scrollPixels : number ; totalScrollPixels : number } {
521+ private _getScrollPixels ( ) : { scrollPixels : number ; totalScrollPixels : number } {
519522 const el = this . scrollbarEle ;
520523 const axis = this . options . scrollAxis ;
521524
@@ -541,13 +544,13 @@ export default class ScrollFrameCanvas extends EventEmitter {
541544 }
542545 }
543546
544- private _handleScroll ( ) : void {
547+ private _handleScroll ( ) : void {
545548 if ( ! this . _playing ) return ;
546549 // 只更新帧索引,不直接绘制
547550 this . _currentFrame = this . _calcFrameFromScroll ( ) ;
548551 }
549552
550- private _tick ( ) : void {
553+ private _tick ( ) : void {
551554 if ( ! this . _playing ) return ;
552555 this . _rAFId = requestAnimationFrame ( ( ) => {
553556 // 检查当前帧是否需要绘制
@@ -569,14 +572,15 @@ export default class ScrollFrameCanvas extends EventEmitter {
569572 } ) ;
570573 }
571574
572- private _calcFrameFromScroll ( ) : number {
575+ private _calcFrameFromScroll ( ) : number {
573576 const total = this . getTotalFrames ( ) ;
574577 const { scrollPixels, totalScrollPixels } = this . _getScrollPixels ( ) ;
575578 const frameIndex = this . options . frameMapper ( scrollPixels , totalScrollPixels , total ) ;
576579 return clamp ( Math . round ( frameIndex ) , 0 , total - 1 ) ;
577580 }
578581
579582 private _renderIfNeeded ( force : boolean = false , usePrevRealFrame = false ) {
583+ if ( this . _destroyed ) return ;
580584 const frame = this . _currentFrame ;
581585 if ( ! force ) {
582586 if ( frame === this . _lastDrawnFrame ) {
@@ -628,6 +632,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
628632 }
629633
630634 private _drawPreRenderedFrame ( preRenderedFrame : ImageBitmap ) : void {
635+ if ( this . _destroyed ) return ;
631636 if ( ! this . ctx ) return ;
632637
633638 const ctx = this . ctx ;
@@ -638,7 +643,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
638643 ctx . drawImage ( preRenderedFrame , 0 , 0 , canvasW , canvasH ) ;
639644 }
640645
641- private _startLoadingAnimation ( ) {
646+ private _startLoadingAnimation ( ) {
642647 this . _loadingProgress = 0 ;
643648 this . _loadingProgressCount = 0 ;
644649 this . _loadingCompleted = false ;
@@ -647,11 +652,12 @@ export default class ScrollFrameCanvas extends EventEmitter {
647652 private _stopLoadingAnimation ( ) : void {
648653 this . _loadingCompleted = true ;
649654 cancelAnimationFrame ( this . _loadingAnimationId ) ;
650- this . _loadingAnimationId = 0 ;
651- // 清空画布
652- if ( this . ctx ) {
653- this . ctx . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
654- }
655+ this . _loadingAnimationId = 0 ;
656+ if ( this . _destroyed ) return ;
657+ // 清空画布
658+ if ( this . ctx ) {
659+ this . ctx . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
660+ }
655661 }
656662
657663 private _updateLoadingProgress ( ) : void {
@@ -667,7 +673,8 @@ export default class ScrollFrameCanvas extends EventEmitter {
667673 this . _loadingAnimationId = requestAnimationFrame ( animate ) ;
668674 }
669675
670- private _drawLoadingAnimation ( ) : void {
676+ private _drawLoadingAnimation ( ) : void {
677+ if ( this . _destroyed ) return ;
671678 if ( this . _loadingCompleted ) return ;
672679 if ( ! this . ctx ) return ;
673680
@@ -760,6 +767,7 @@ export default class ScrollFrameCanvas extends EventEmitter {
760767 }
761768
762769 private _drawBackgroundLoadingAnimation ( ) : void {
770+ if ( this . _destroyed ) return ;
763771 if ( this . _backgroundLoadingCompleted || ! this . ctx ) return ;
764772 if ( ! this . options . large ?. showBackgroundProgress ) return ;
765773 this . _renderIfNeeded ( true , true ) ;
0 commit comments