gabrielcsapo/docusaurus-plugin-image-zoom

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

Opened this issue · 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?

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.

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.

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

So instead of this:

onRouteUpdate() {
setTimeout(() => {
if(zoomObject)
zoomObject.detach();
zoomObject = mediumZoom(selector, config);
}, 1000);

Something like this:

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

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

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

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

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

2m commented

@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? :)

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