fancyapps / ui

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

How to set the default zoom magnification for images? #585

Closed Container-Zero closed 1 year ago

Container-Zero commented 1 year ago

Hello, I have been confused about the panzoom setting options:

For example, when set to contentDblClick: "toggleZoom"

  1. How to set the default zoom magnification for images? When I double click on an image, the image is zoomed in, but the zoom seems to be determined automatically based on the size of the image and the screen size of the device? What should I do if I want to ignore the effect of the browser window size and force the image to scale to 1.2 times the original image after double click?

  2. What does maxScale actually do? There is a maxScale in panzoom which seems to limit the magnification of an image to a certain value, but why is it that when I set maxScale to 1, double clicking on an image still zooms it to a higher magnification?

  3. Can I add a dom attribute like data-scale to control the zoom rate of each image independently? Sometimes my images vary greatly in size or center of gravity, and I would like to be able to set a different double-click zoom magnification for each image to allow users to quickly focus on the magnification that should be the focus of the image when zooming in on the product, is this possible?

fancyapps commented 1 year ago

Hi,

1) Check https://fancyapps.com/panzoom/zoom-levels/ there are demos to explain the use of the maxScale option. 2) I can't imagine how it would work, because you also have to take into account that the user could use a small screen device (phone) or extra wide monitor. Maybe you can give some demos with the description of the desired result.

Container-Zero commented 1 year ago

Hi,

  1. Check https://fancyapps.com/panzoom/zoom-levels/ there are demos to explain the use of the maxScale option.
  2. I can't imagine how it would work, because you also have to take into account that the user could use a small screen device (phone) or extra wide monitor. Maybe you can give some demos with the description of the desired result.
  1. thanks for the tip, I probably understand. The current scaling logic is the scaling in terms of the original resolution of the image and the scaling limits.

  2. The whole zoom logic in my thinking is like this: The image is displayed in the gallery, and after that the zoom is not based on the size of the original image, but directly on the current display base size, similar to transform: scale(1.5).

    The reason for doing this is also simple, for example: When your image is a super high resolution image like 8k, if it is always scaled to the original resolution of the image, then on a user's 1k resolution screen the image will be scaled up by a factor of 8, and on a mobile user the image will be scaled up by a staggering factor of 16. This is a very unreasonable magnification, for any image, you can hardly see anything at 16x magnification, the user will be confused and will surely take a second action to reduce the image. See: https://stackblitz.com/edit/web-platform-tcjjgs?file=index.html

    It would be much more common for all resolutions if you could always zoom in on the original image with a specified magnification (e.g. transform: scale(1.5)) on top of the default displayed. At the same time, the user can continue to zoom in up to our specified magnification of transform: scale([Max]).

  3. So the (3) in the first question also builds on the (2) in the current question, where each image can set a transform: scale([?]) to customize the scaling multiplier?

My thinking and reasoning is based on my understanding of the current scaling, so I can't rule out the possibility of a logical error. As well as perhaps there are currently other options that can better handle the problem I'm having in (2)?

fancyapps commented 1 year ago

Well, I'll think about it.

btw, one of the reasons why there wasn't a fixed zoom level increase in the first place is that if you, for example, get almost full size after the first click, then the second click will be weird. Example: if you open 1000px wide image, but it is resized to fit to 640px and you set to scale 1.5x on click, then at first click it would scale from 640px to 960px, but only from 960px to 1000px on the second click.

Container-Zero commented 1 year ago

Well, I'll think about it.

btw, one of the reasons why there wasn't a fixed zoom level increase in the first place is that if you, for example, get almost full size after the first click, then the second click will be weird. Example: if you open 1000px wide image, but it is resized to fit to 640px and you set to scale 1.5x on click, then at first click it would scale from 640px to 960px, but only from 960px to 1000px on the second click.

The case you're talking about would be when acting on contentDblClick: "iterateZoom", whereas the ideal case I'd expect would be based on something like contentDblClick: "toggleZoom" which only scales once:

After my investigation, the closest method to transform: scale(1.5) is Fancybox.getSlide().panzoom.zoomTo(1.5); This is a great way to customize the magnification, but it doesn't seem to have a way to be similar to toggleCover, toggleMax, and toggleZoom to be able to set it in the contentDblClick option and implement an on/off function. For example, the following pseudo-code: contentDblClick: "toggleTo([1.5,1])", with a zoom flow of (1 → 1.5 → 1), seems like it would allow for more freedom in zooming if it could be set up this way.

Also, your concern is the main reason I'm considering requirement (3), when I have very few diagrams, and at the same time large differences in image resolution, being able to set the zoom scheme for each diagram individually would be a tantalizing setup option as well.

fancyapps commented 1 year ago

Well, you could also completely customize click event, like this:

Fancybox.bind("[data-fancybox]", {
  Images: {
    Panzoom: {
      on: {
        click: (panzoom, event) => {
          event.preventDefault();

          if (panzoom.scale > 1) {
            panzoom.zoomTo(1);
          } else {
            panzoom.zoomTo(1.5);
          }
        },
      },
    },
  },
});
Container-Zero commented 1 year ago

Well, you could also completely customize click event, like this:

Fancybox.bind("[data-fancybox]", {
  Images: {
    Panzoom: {
      on: {
        click: (panzoom, event) => {
          event.preventDefault();

          if (panzoom.scale > 1) {
            panzoom.zoomTo(1);
          } else {
            panzoom.zoomTo(1.5);
          }
        },
      },
    },
  },
});

Yes, that's exactly what I'm currently doing with the extra code to customize the magnification with a double click:

contentDblClick:() => {
    if (window.fancyboxDblClickTimeOut) {
        if(Fancybox.getSlide().panzoom.scale == 1) Fancybox.getSlide().panzoom.zoomTo(2.2);
        else Fancybox.getSlide().panzoom.zoomTo(1);
        clearTimeout(window.fancyboxDblClickTimeOut);
        window.fancyboxDblClickTimeOut = undefined;
    } else {
        window.fancyboxDblClickTimeOut = setTimeout(function() {
            window.fancyboxDblClickTimeOut = undefined;
        }, 300);
    }
    return false;
},

But in the end I don't know how to be able to zoom towards the center of the mouse click like toggleZoom. Can you give advice on this? Also, it might be a tempting thing to bring this part of the functionality with you? Perhaps you could consider whether fancybox needs this part of the functionality.

fancyapps commented 1 year ago

You can pass event to zoomTo method, then it will be used to calculate centering -

Fancybox.bind('[data-fancybox]', {
  compact: false,

  Images: {
    Panzoom: {
      on: {
        click: (panzoom, event) => {
          event.preventDefault();

          if (panzoom.targetScale > 1) {
            panzoom.zoomTo(1);
          } else {
            panzoom.zoomTo(2, { event });
          }
        },
      },
    },
  },
});

https://stackblitz.com/edit/web-platform-ega6x8?file=index.html

Container-Zero commented 1 year ago

You can pass event to zoomTo method, then it will be used to calculate centering -

Fancybox.bind('[data-fancybox]', {
  compact: false,

  Images: {
    Panzoom: {
      on: {
        click: (panzoom, event) => {
          event.preventDefault();

          if (panzoom.targetScale > 1) {
            panzoom.zoomTo(1);
          } else {
            panzoom.zoomTo(2, { event });
          }
        },
      },
    },
  },
});

https://stackblitz.com/edit/web-platform-ega6x8?file=index.html

Thank you very much, the customization method is working perfectly so far!