Reputation: 673
I'm working on a image sequence animation and I came across a problem when a new user enters the site for the first time:
Once I have loaded the images from the external database the full screen loading animation removes itself from the screen but now when the user enters the animation, all the images has not been loaded yet so the animation seems buggy & broken. After few seconds all the images has loaded and the animation works just like it should.
So my question is how can I wait till all images has been loaded fully before removing the loading animation to prevent the user from using the animation while the images are still loading?
Here's the function for getting the images:
async getImages(state) {
var images = []
for (let i = 0; i < state.frameCount; i++) {
var imgIndex = (i + 1).toString().padStart(4, '0')
const img = new Image();
img.index = Number(imgIndex)
img.id = imgIndex
var storageRef = this.$fire.storage.ref(`/web-2-160-final.${imgIndex}.png`);
storageRef.getDownloadURL().then((url) => {
console.log('IMG URL',url)
var imgSrc = url
img.src = imgSrc;
img.classList.add('full-screen')
images.push(img);
function percentage(partialValue, totalValue) {
state.percentage = (100 * partialValue) / totalValue
}
percentage(images.length, state.frameCount)
if(images.length == state.frameCount) setImages()
})
}
const setImages = () => {
state.isLoaded = true
var lowestToHighest = images.sort((a,b) => a.index - b.index)
console.log('NEW ARRAY', lowestToHighest)
state.images = images
console.log(state.images)
}
},
Upvotes: 0
Views: 391
Reputation: 20954
First loop over all the download URLs that you need for each image. Collect each Promise
returned from every storageRef.getDownloadURL()
call.
Wait for every URL to be retrieved with Promise.all()
. This ensures that the code waits until every URL is retrieved and ensures that the order remains in the correct order.
Then loop over every URL and create an image for each URL. Use the onload
event of the image to return the image whenever it is finished loading. Collect everything in an array of promises and await it again with Promise.all()
.
The result should be an array of (loaded) images in the order you provided.
async getImages(state) {
const downloadUrls = [];
for (let i = 0; i < state.frameCount; i++) {
const imgIndex = (i + 1).toString().padStart(4, '0');
const storageRef = this.$fire.storage.ref(`/web-2-160-final.${imgIndex}.png`);
const downloadUrl = storageRef.getDownloadURL();
downloadUrls.push(downloadUrl);
}
const urls = await Promise.all(downloadUrls);
let amountOfPreloadedImages = 0;
const images = await Promise.all(urls.map(url =>
new Promise((resolve, reject) => {
const image = new Image();
image.src = url;
image.onload = () => resolve(image);
image.onerror = (error) => reject(error);
}).then(image => {
amountOfPreloadedImages++;
state.percentage = 100 * amountOfPreloadedImages / state.frameCount;
return image;
})
));
state.images = images;
}
Upvotes: 1