zooming
zooming copied to clipboard
Add a spinner while loading fullsize image
Hi there!
Actually when clicking on an image, Zooming
doesn't provide any visual information to let the user know a better resolution image will show when loaded.
This can be a problem on devices with poor connection as users might close the Zoomed
image before the full size image is displayed.
To let users know something better is coming, what do you think about adding a div with a css spinner while the full size image is loading.
Thanks for the good work on this awesome library btw 😄 !!
Cheers
Yeah this is a good idea. However, I want to be careful about making it an opt-in feature because some people might not needed it. Maybe we can introduce two new event hooks onImageLoading
and onImageLoaded
, then user can add/remove loading indicator with their own styling. I'll experiment with it and see how it goes :)
- https://stephanwagner.me/only-css-loading-spinner
Adding new event hooks also make sens for customisation, everyone will be able to add their own spinner design. That sounds great!
The above two event hooks have been added to the latest release 2.1.0
:
But I haven't figured out the most appropriate way to indicate the loading status yet. One thing I'm sure about is that we need to set a certain time threshold for the indicator to only show up in slow internet connection or the first fetch, otherwise it blinks which is a bit annoying.
One thing I'm sure about is that we need to set a certain time threshold for the indicator to only show up in slow internet connection or the first fetch, otherwise it blinks which is a bit annoying.
Turbolinks does this with a 500ms delay before showing the progress bar. I doubt this is based on any UX study, but I quite like the value.
Hey @kingdido999,
Thanks for the new release!
I've wrote a promise function to check image load properly.
I use it to lazyload image everyday, it's pretty solid!
You can probably improve the new event onImageLoaded
with it.
/**
* Method to fetch image from source
*
* @param {URL} imgSource
* @returns {Promise}
*/
const fetchImage = imgSource => {
// Return a promise to fetch the image
return new Promise((resolve, reject) => {
// Create a new image
const imgElement = new Image()
// Define events callbacks
const loadCallback = () => {
// Remove events listener
imgElement.removeEventListener('load', loadCallback)
imgElement.removeEventListener('error', errorCallback)
// Resolve Promise
resolve()
}
const errorCallback = () => {
// Remove events listener
imgElement.removeEventListener('load', loadCallback)
imgElement.removeEventListener('error', errorCallback)
// Reject Promise
reject(Error(`Error while loading image at ${imgSource}`))
}
// Listen to load and error events on image
imgElement.addEventListener('load', loadCallback)
imgElement.addEventListener('error', errorCallback)
// Set image source
imgElement.src = imgSource
})
}
You can use it like so:
fetchImage(imgSource).then(() => { console.log('image loaded') })
About the time threshold, as usage will probably be different for each case, I suggest you to simply add an exemple into the doc.
In the end it's simple as adding a timeout to onImageLoaded
callback... nope?
Lastly to prevent the problem of the first fetch you could create an empty loaded
array that will be filled as data-original
source are loaded:
let loaded = []
if (loaded[imgIndex] === true) {
onImageLoaded()
} else {
fetchImage(imgSource).then(() => {
onImageLoaded()
loaded[imgIndex] = true
})
}
This will help not impact performances.
Hi @kingdido999!
Can we have your input on this please?
Tks