worka / vanilla-js-wheel-zoom

Image resizing using mouse wheel (pinch to zoom) + drag scrollable image (as well as any HTML content)
https://worka.github.io/vanilla-js-wheel-zoom
MIT License
168 stars 31 forks source link

When the image at maxScale is smaller than the viewport #35

Closed GunArm closed 1 year ago

GunArm commented 1 year ago

This script is terrific. I'm using it in a custom lightbox.

Although my main interest is to view very large images with particular interest to be seen up close, it is not known ahead of time which images will be shown in it, so some small images will inevitably also be loaded. I do not want the small images (or the large ones) to be zoomed into pixels, so the maxScale option is very handy.

However I have noticed that if the viewport is larger than the (image * maxScale), there is odd behavior:

I would have expected that if the image is smaller than the viewport (at max scale), it would be loaded at max scale and centered, with further zoom-in attempts doing nothing (because it's already at max scale).

Is this a known issue/unsupported? Or does it sound like I have done something strange?

For reference, this is effectively how I have it loaded.

      <style>
        #myViewport {
          height: 100%;
          width: 100%;
          background-color: darkkhaki;
          display: flex;
          align-items: center;
          justify-content: center;
          overflow: hidden;
          position: relative;
        }

        #myViewport img {
          cursor: grab;
          position: absolute;
        }
      </style>
      <script src="/assets/js/wheel-zoom.min.js"></script>

      <div id="myViewport">
        <img id="myContent" src="" alt="image" />
      </div>
      <script>
        var zoomContent = document.getElementById('myContent');
        WZoom.create('#myContent',{
          type: 'image',
          zoomOnDblClick: true,
          smoothTime: 0,
          maxScale: 1,
          dragScrollableOptions: {
              onGrab: function () {
                  zoomContent.style.cursor = 'grabbing';
              },
              onDrop: function () {
                  zoomContent.style.cursor = 'grab';
              }
          }
        }); /**/
      </script>
GunArm commented 1 year ago

The calculation for minScale in _prepare() assumes that the image will be larger than the viewport. If it is not, it will return a minScale (as a ratio of viewPort to content) which is greater than 1. The default maxScale is 1, and the result is that with a minScale > maxScale, _computeScale(...) logic leads it to effectively alternate between maxScale and (larger) minScale.

This seems at least superficially to fix it, although I wouldn't presume to know if it might have other implications. The result for me is that an image smaller than the viewport is shown centered in the viewport and cannot zoom, which is ideal for my purposes.

             } else {
                 content.originalWidth =
                     options.width || content.$element.offsetWidth;
                 content.originalHeight =
                     options.height || content.$element.offsetHeight;
             }
             content.minScale =
                 options.minScale ||
                 Math.min(
                     viewport.originalWidth / content.originalWidth,
-                    viewport.originalHeight / content.originalHeight
+                    viewport.originalHeight / content.originalHeight,
+                    options.maxScale,
+                    1
                 );
             content.maxScale = options.maxScale;
             content.currentScale = content.minScale;
             content.currentWidth = content.originalWidth * content.currentScale;
             content.currentHeight =
                 content.originalHeight * content.currentScale;
worka commented 1 year ago

This behavior looks like a bug ))) (but on the other hand, this is not the task of this plugin - show little image)

I'm glad you made the fix for yourself. I do not have time to deal with this problem right now, but as soon as I am free, I will try to fix it and trigger you.

GunArm commented 1 year ago

I totally understand that it isn't meant to show small images, this is more of an edge case, not knowing ahead of time exactly what content might go into it. No rush on my account, I just wanted to contribute back what I figured out. Thank you for making this great plugin available!

worka commented 1 year ago

I fixed it. Pls check and close issue if all done.

GunArm commented 1 year ago

Works well. Thanks again!