platjs
Version:
Simple engine for platformer physics and rendering
81 lines (69 loc) • 2.56 kB
text/typescript
function loadImage(
name: string,
url: string,
onProgress: (loaded: number, total: number) => void = () => {}
): Promise<{ name: string; img: HTMLImageElement }> {
return new Promise((resolve, reject) => {
const img = new Image();
// img.addEventListener('load', () => {
// resolve({name: name, img: img});
// });
// img.addEventListener('error', (e) => reject(e));
// img.src = url;
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", () => {
if (xhr.status === 200) {
const blob = new Blob([xhr.response]);
img.addEventListener("load", () => {
resolve({ name: name, img: img });
});
img.addEventListener("error", () => {
reject("image failed to load");
});
img.src = URL.createObjectURL(blob);
} else {
reject("failed status: " + xhr.status.toString());
}
});
xhr.addEventListener("progress", (e) => {
if (e.lengthComputable) {
onProgress(e.loaded, e.total);
} else {
// average image size
onProgress(0, 8.1 * 1000); // https://www.pingdom.com/blog/new-facts-and-figures-about-image-format-use-on-websites/#:~:text=Average%20image%20size%20per%20format,a%20Web%20page%20on%20average.
}
});
xhr.addEventListener("error", () => {
reject("Network error or blocked by cors");
});
xhr.send();
});
}
async function loadImages<T extends { [key: string]: string }>(
images: T,
onProgress: (loaded: number, total: number) => void = () => {}
): Promise<{ [K in keyof T]: HTMLImageElement }> {
const loadedNumbers = Object.keys(images).map(() => 0);
const totalNumbers = Object.keys(images).map(() => 1);
const imgs = Object.keys(images).map((key, idx) =>
loadImage(key, images[key], (loaded, total) => {
// console.log(key, (loaded / total) * 100);
loadedNumbers[idx] = loaded;
totalNumbers[idx] = total;
onProgress(
loadedNumbers.reduce((a, b) => a + b),
totalNumbers.reduce((a, b) => a + b)
);
})
);
const loadedImgs = await Promise.all(imgs);
const finishedImgs: { [key: string]: HTMLImageElement } = {};
loadedImgs.forEach(({ name, img }: { name: string; img: HTMLImageElement }) => {
finishedImgs[name] = img;
});
return finishedImgs as unknown as any;
}
export default loadImages;
export { loadImage };