fancyapps / ui

A library of JavaScript UI components, includes the best lightbox - Fancybox5
https://fancyapps.com/
Other
814 stars 98 forks source link

Zoom into original image when using `srcset` in Fancybox #380

Open mikaraunio opened 1 year ago

mikaraunio commented 1 year ago

When using data-srcset, zooming zooms into the currently selected source of the srcset. If the source sizes are judiciously selected, the image is already appropriately sized for the viewport, so very little zooming actually happens. Or, if data-width and data-height were specified, the image is indeed zoomed to those dimensions, but the source is not switched, which can cause upscaling.

Is there a way to always use the original (href / data-src) image for zooming instead? I understand this can cause a delay as the image may need to be loaded when the zoom action is triggered (and prefetching the original would defeat the point of using srcset).

Observed with latest Fancybox on MacOS Chrome 107.

fancyapps commented 1 year ago

Hi,

Sorry, but could you clarify your question? It would be great if you could describe step by step what is happening on each action, and what would you like to see instead.

mikaraunio commented 1 year ago

Sure @fancyapps.

What is happening

Supposing the following code:

<a data-fancybox="gallery" 
   href="/width-1600.jpg"
   data-srcset="/width-576.jpg 576w, /width-768.jpg 768w, /width-1200.jpg 1200w, /width-1600.jpg 1600w"
   data-sizes="(max-width: 576px) 576px, (max-width: 768px) 768px, (max-width: 1200px) 1200px, 1600px">
  <img src="/thumbnail.jpg">
</a>

Steps:

  1. The user has a viewport 700px wide (and a pixel ratio of 1)
  2. Click on thumbnail, Fancybox opens
  3. /width-768.jpg is displayed by the browser
  4. The user clicks the image to zoom in
  5. The image is zoomed to 768px wide, /width-768.jpg remains the image source

If the tag also contains data-width and data-height:

<a data-fancybox="gallery" 
   href="/width-1600.jpg"
   data-srcset="/width-576.jpg 576w, /width-768.jpg 768w, /width-1200.jpg 1200w, /width-1600.jpg 1600w"
   data-sizes="(max-width: 576px) 576px, (max-width: 768px) 768px, (max-width: 1200px) 1200px, 1600px"
   data-width="1600" data-height="900">
  <img src="/thumbnail.jpg">
</a>

Then step 5 becomes:

  1. The image is zoomed to 1600px wide, but /width-768.jpg remains the image source, and the image is thus upscaled

What I would like to see instead

  1. The image is zoomed to 1600px wide, and the source is switched to the href image, /width-1600.jpg
fancyapps commented 1 year ago

Well, the idea of Fancybox (or any similar lightbox-type script) is that you point to the full size image. When the image is loaded, it is displayed resized, if needed. User can then click, use mouse wheel, or use a pinch gesture to see the full size.

I will consider your feature request to change the image source depending on the scale

mikaraunio commented 1 year ago

Well, the idea of Fancybox (or any similar lightbox-type script) is that you point to the full size image.

Sorry, I'm not sure what you mean – are you saying that you recommend using Fancybox with full-size images only, and that using data-srcset goes against the idea of the library?

To me, using srcset for the gallery and the original for zooming would make sense:

srcset allows the gallery to show the image renditions that are the best fit for the user's viewport. This saves bandwidth and enables faster loading. Users will probably not zoom most of the images, so there's no need to always load the highest resolution originals when a smaller 800px (for example) rendition is enough to fill the viewport.

When the user does want to zoom in on a particular image however, the smaller rendition loaded from the srcset is not very useful, as it is already sized for the viewport so there's not much to zoom in. Switching to the original image would help here.

Example bandwidth calculation

With the 800px viewport mentioned above, let's assume 800px renditions are 0.5MB each, and original images are 2MB each.

The users goes through a gallery of 10 images, ands zooms into one of them.

Total bandwidth with originals: 10 * 2MB = 20MB

Total bandwidth with srcset and "zoom to original": 10 * 0.5MB + 2MB = 7MB

Bandwidth savings: 65%.

Thanks for considering this.

fancyapps commented 1 year ago

The idea is that you use srcset to choose the most appropriate full image size. For example, if your original image is 4032px wide, it's quite cumbersome to view it on a device that has, say, a 320px wide viewport. Also, you might run into performance issues trying to display too large image. Then you could choose a smaller image size.

But, of course, it depends on the use case. Maybe you want to present your highly detailed photos. But you would also want to save bandwidth. In such case it would be best to load only part of the image when user zooms, but then you would have to create tiles and in the end, Fancybox would work similarly to Leaflet.js and others. Actually, at some point I explored possibilities to make Fancybox work with tile providers, but, since it adds quite a lot of complexity, decided to postpone it. Also, I am not sure how many users would find it useful.

mikaraunio commented 1 year ago

I agree that tiling feels overkill. However, maybe just using srcset to select the most appropriate image for the current zoom level would be good enough? This seems to be the approach chosen by PhotoSwipe for example.

LightGallery also seems to support this already, so there is probably at least some user demand for this.

fancyapps commented 1 year ago

Are you really 100% sure PhotoSwipe works exactly as you imagined? Maybe I am missing something, but it actually works the same as Fancybox, except it does zoom animation on the thumbnail image and then switches to the full image size. Fancybox v3 works the same, but some users complained that switching images looks like a bug, not a feature, therefore in v4 it was dropped (interestingly, no one has asked to bring that back yet).

mikaraunio commented 1 year ago

I do believe it does. See https://photoswipe.com/getting-started/#responsive-images-with-srcset and try the demo in that section in a smaller window responsive preview.

Attaching a screen recording below to illustrate.

https://user-images.githubusercontent.com/5990360/204100114-003c1297-9b46-46a1-968b-e1e067e7eafd.mov