docusaurus-plugin-image-zoom icon indicating copy to clipboard operation
docusaurus-plugin-image-zoom copied to clipboard

Plugin doesn't work properly with @docusaurus/plugin-ideal-image

Open nomicode opened this issue 2 years ago • 7 comments

Hello again!

I have discovered a bug when using this plugin with the @docusaurus/plugin-ideal-image plugin.

Initially, the ideal images plugin renders images to the document like this:

<div style="background-size:cover;background-repeat:no-repeat;position:relative;background-image:url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAqElEQVQImW1MSw6CMBTsXSFaYMuGK3iYhpWRCxjXXMJGW2AFtLzpmMadcZLJfDIZ1bZt1zT1TZ9PRuuq11r3ZVn2RVFkb3RVDXVdd+rtp2GaPGf/ovMT53nmsiz03vFpLa21dM4Nat12s64rgRRCCLJtm+z7LiQzwyHC4ziMEhEj3xBFIBkxRgEgTCmSJACjEnDNIaWU5S8AXPPjBcAI4A7g8cPcjXnzAd6h0YQCl765AAAAAElFTkSuQmCC&quot;)">
<svg style="width:100%;height:auto;max-width:100%;margin-bottom:-4px" width="640" height="390"></svg>
<noscript>
<img style="width:100%;height:auto;max-width:100%;margin-bottom:-4px;position:absolute;top:0;left:0" src="/assets/ideal-img/cmp-profile-drop-down.478bbdf.640.png" srcset="/assets/ideal-img/cmp-profile-drop-down.478bbdf.640.png 640w,/assets/ideal-img/cmp-profile-drop-down.c4b3d9d.1120.png 1120w,/assets/ideal-img/cmp-profile-drop-down.dc3b452.1600.png 1600w,/assets/ideal-img/cmp-profile-drop-down.c7b8e12.2080.png 2080w,/assets/ideal-img/cmp-profile-drop-down.a465585.2560.png 2560w" alt="A  screenshot of the profile drop-down menu" width="640" height="390">
</noscript>
</div>

Then, when the div element enters the viewport, it gets mutated to:

<div style="background-size: cover; background-repeat: no-repeat; position: relative;">
<img src="/assets/ideal-img/cmp-profile-drop-down.c7b8e12.2080.png" alt="A  screenshot of the profile drop-down menu" width="640" height="390" style="width: 100%; height: auto; max-width: 100%; margin-bottom: -4px;" class="medium-zoom-image">
</div>

However, it looks like the replacement image doesn't get passed to a mediumZoom function call, meaning that any images that load in as you scroll are not zoomable.

I notice that you're observing attributes to update the background color (presumably for when the user switch between light and dark mode). I also notice that you seem to be waiting for new page loads, so that you can reinitialize the zoomObject for any new images.

(Please note, I am not a JavaScript developer, so all of this is just my best guess.)

Do you think it would be possible to fix this issue by observing for subtree mutations on the article elements, and then reinitializing the zoomObject, like you do with a new page?

nomicode avatar May 23 '22 10:05 nomicode

I tried the plugin-image-zoom, but that plugin fails in a different way. It seems to get confused by the initial placeholder image. As a result, every IdealImage component is initialized twice. This produces buggy behavior:

  • When you click to zoom, two zoom boxes open, with the second white background div obscuring both
  • When you click to close, it closes the second zoom container, and you can see a zoomed image with no white background div
  • When you click to close a second time, the page returns to normal

I also tried the Zoom component used by the official Docusaurus docs. It's a bit more work, having to embed each IdealImage component within a Zoom component, but it does seem to correctly initialize each image only once. However, this method produces a different issue:

  • When you click to zoom, the original placeholder image is zoomed, and then the placeholder is replaced with the actual image

The time for the actual image to load in is small, but it is noticeable every time you zoom, and I think it looks broken.

Your plugin is the only thing I have found so far that correctly zooms the IdealImage component. The only issue is that, at the moment, it only ever initializes the zoomObject with whatever IdealImage components happen to be visible within the viewport when the page loads.

nomicode avatar May 23 '22 10:05 nomicode

I have set up Netlify to host a built version of the site I am working on so you can test the behavior for yourself.

  • Visit https://628b626f5890890008b3346d--doitintl-help.netlify.app/docs/general/log-in

    • If the IdealImage at the top of the page loaded in after the zoomObject was initialized, you will not be able to zoom the image.
    • If you refresh the page, if the image loads in fast enough from your cache, the zoomObject will be initialized properly, and you should be able to zoom.
  • Visit https://628b626f5890890008b3346d--doitintl-help.netlify.app/docs/general/profile

    • Notice that the first image zooms correctly, but any images that load as you scroll further down the screen are not zoomable. I think this is because they are only loaded in by IdealImage after the initial zoomObject has been initialized.
  • Visit https://628b626f5890890008b3346d--doitintl-help.netlify.app/docs/general/slack

    • Scroll down the page to find the images. Notice that none of the images are zoomable. I think this is because all images are loaded after the initial zoomObject has been initialized.

nomicode avatar May 23 '22 10:05 nomicode

My guess is that the onRouteUpdate handler could be replaced with a new observer that monitors article subtree mutations.

So instead of this:

https://github.com/gabrielcsapo/docusaurus-plugin-image-zoom/blob/b6e0fc72b525dab4d1aececbd3b0f558724e3d2c/src/zoom.js#L42-L47

Something like this:

  var observer = new MutationObserver(function(mutations) {
    if(zoomObject)
      zoomObject.detach();
    zoomObject = mediumZoom(selector, config);
  });

  observer.observe(document.querySelector('article'), { 
    subtree: true
  });

nomicode avatar May 23 '22 10:05 nomicode

I hacked together a solution that works for me. May be interesting?

https://github.com/doitintl/help/pull/88

nomicode avatar Jun 14 '22 23:06 nomicode

@gabrielcsapo would be awesome if the PR mentioned here could be merged. I noticed this small problem too.

Zenahr avatar Jan 31 '23 13:01 Zenahr

@nomicode the linked PR seems to point to a non-existant PR right now. I also noticed the same problem and am looking for a solution. Could you share the code with a fix again? :)

2m avatar May 10 '24 13:05 2m

@nomicode I'm also interested in your deleted PR.

tothero avatar Jul 04 '24 16:07 tothero