Spaces:
Paused
Paused
File size: 2,213 Bytes
3a7a84c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | // src/hooks/useAssetLoader.ts
import { useState, useEffect } from 'react';
// Defines the structure for our asset map
export type AssetSource = {
id: string;
label: string;
src: string;
};
// The hook returns the loaded images and the loading status
export const useAssetLoader = (assets: AssetSource[]) => {
const [loadedImages, setLoadedImages] = useState<
Record<string, HTMLImageElement>
>({});
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
// Reset state when assets change
setIsLoading(true);
setLoadedImages({});
setError(null);
if (assets.length === 0) {
setIsLoading(false);
return;
}
const loadImages = async () => {
try {
const promises = assets.map((asset) => {
return new Promise<void>((resolve, reject) => {
const img = new Image();
// --- THIS IS THE CRITICAL FIX ---
// This attribute tells the browser it's okay to use this cross-origin image on a canvas
// that you intend to capture a stream from.
img.crossOrigin = "anonymous";
// --------------------------------
img.src = asset.src;
img.onload = () => {
setLoadedImages((prev) => ({ ...prev, [asset.id]: img }));
resolve();
};
img.onerror = (err) => {
console.error(
`Failed to load asset: ${asset.label} from ${asset.src}`,
err
);
reject(new Error(`Failed to load ${asset.label}`));
};
});
});
await Promise.all(promises);
} catch (err: unknown) {
console.error("Failed to load one or more assets:", err);
if (err instanceof Error) {
setError(err.message);
} else {
setError("An unknown error occurred during asset loading.");
}
} finally {
setIsLoading(false);
}
};
loadImages();
}, [JSON.stringify(assets)]); // Use stringify to deep-compare the assets array dependency
return { loadedImages, isLoading, error };
}; |