From 0a8056d4e252ceab30da9e19d6118e979e46fef6 Mon Sep 17 00:00:00 2001 From: mkurtic Date: Tue, 27 Jan 2026 09:34:45 +0100 Subject: [PATCH] feature: clear cache on breakpoint change --- .../core/src/frame-loader/frame-loader.ts | 19 +++++++++++++-- packages/core/src/index.ts | 23 +++++++++++++++++++ packages/core/src/types/scrollSequence.ts | 3 +++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/core/src/frame-loader/frame-loader.ts b/packages/core/src/frame-loader/frame-loader.ts index 5ffb482..cff59f4 100644 --- a/packages/core/src/frame-loader/frame-loader.ts +++ b/packages/core/src/frame-loader/frame-loader.ts @@ -96,6 +96,7 @@ class FrameLoader { this.activeBreakpoint.frames[index] = stat; this.loadingFrames.delete(index); + return; } catch (error) { lastError = error; if (attempt < this.maxRetries) { @@ -140,9 +141,23 @@ class FrameLoader { private loadInternal(src: string): Promise { return new Promise((resolve, reject) => { const img = new Image(); - img.onload = () => resolve(img); - img.onerror = (e) => reject(e); img.src = src; + + if (typeof (img as HTMLImageElement).decode === "function") { + img.decode() + .then(() => resolve(img)) + .catch(() => { + if (img.complete) { + resolve(img); + return; + } + img.onload = () => resolve(img); + img.onerror = (err: unknown) => reject(err); + }); + } else { + img.onload = () => resolve(img); + img.onerror = (e: unknown) => reject(e); + } }); } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 1b6a9d7..4df492d 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -29,11 +29,13 @@ export class ScrollSequenceEngine { private prefersReducedMotion: PrefersReducedMotion | null = null; private dpr: number = 1; private resizeObserver: ResizeObserver | null = null; + private clearCacheOnBreakpointChange: boolean = false; constructor(config: ScrollSequenceProps) { this.config = config; this.breakpoints = []; this.prefersReducedMotion = new PrefersReducedMotion(); + this.clearCacheOnBreakpointChange = config.clearCacheOnBreakpointChange ?? false; this.dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1; const canvasRenderProps = { @@ -99,6 +101,8 @@ export class ScrollSequenceEngine { this.scrollConfig = this.normalizeScrollConfig(config.scrollConfig); this.loadingConfig = this.normalizeLoadingConfig(config.loadingConfig); + + this.scrollEngine = new ScrollEngine({ containerRef: config.container, totalFrames: fallbackOnly ? 1 : this.totalFrames, @@ -135,6 +139,25 @@ export class ScrollSequenceEngine { this.normalizeFramesRange(this.activeBreakpoint); this.initFramesLoadingManager(); await this.initFramesLoadings(); + if(this.clearCacheOnBreakpointChange){ + this.breakpoints.forEach((breakpoint) => { + if (breakpoint.name !== this.activeBreakpoint?.name) { + breakpoint.frames.forEach((frame) => { + if (!frame || !frame.image) return; + + if (frame.image.src.startsWith("blob:")) { + URL.revokeObjectURL(frame.image.src); + } + + frame.image.src = ""; + frame.image.onload = null; + frame.image.onerror = null; + frame.image = null; + }); + breakpoint.frames = []; + } + }); + } }); }; diff --git a/packages/core/src/types/scrollSequence.ts b/packages/core/src/types/scrollSequence.ts index be4ef2b..e28605c 100644 --- a/packages/core/src/types/scrollSequence.ts +++ b/packages/core/src/types/scrollSequence.ts @@ -143,6 +143,9 @@ export interface ScrollSequenceProps { /* Canvas's container */ container: HTMLElement; + + /** Whether to clear the cache when the breakpoint changes (default: false) */ + clearCacheOnBreakpointChange?: boolean; } export interface BreakpointConfig {