fancyapps / ui

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

Infinite gallery #71

Closed zub0r closed 10 months ago

zub0r commented 3 years ago

First of all, thanks for this great plugin!

The example from the docs shows single images in the gallery instead of two listed images. https://fancyapps.com/docs/ui/fancybox/api#initialization

<div id="gallery">
  <a href="https://lipsum.app/id/1/800x600">
    <img src="https://lipsum.app/id/1/300x225" />
  </a>

  <a href="https://lipsum.app/id/2/800x600">
    <img src="https://lipsum.app/id/2/300x225" />
  </a>
</div>

<script>
  Fancybox.bind("#gallery a", {
    on : {
      ready : (fancybox) => {
        console.log(`fancybox #${fancybox.id} is ready!`);
      }
    }
  });
</script>

I'd like to use the bind method to observe the container for elements and add slides dynamically (I use infinite scroll in the grid).

fancyapps commented 3 years ago

Hi,

Unfortunately, there is so much to do, and I have not yet updated the documentation to reflect recent changes. So, either use the groupAll option to group them all, or add data-fancybox attribute to your links, see this demo for different uses - https://fancyapps.com/playground/w6

zub0r commented 3 years ago

Thanks for the fast reply, that's what I was looking for. Is there a way to dynamically add new slides to an opened gallery from the DOM? Something like a reload? Thanks

fancyapps commented 3 years ago

Sorry, it is currently not possible to add / remove slides from an already open instance. You could do something like this to destroy and reinitialize Carousel, but it is not optimized and there can be glitches:

Fancybox.getInstance().items.push({src : "https://lipsum.app/id/99/300x200/", type : "image"});
Fancybox.getInstance().Carousel.destroy();
Fancybox.getInstance().initCarousel();

Anyway, your goal is to create something like infinite gallery? Sometimes people ask for it, but I think it's useless. I believe it would be best to display maximum 20 or 25 images on the page, but include all images in the Fancybox. Unless you really have infinite number images, you can easily use Fancybox to display hundreds of images. Fancybox (and thumbnail carousel) will load visible images and next/prev items (you can configure that).

zub0r commented 3 years ago

Thanks. My use case is that I'm loading hundreds of items to the grid with infinite scroll in sets of 20-30 (imagine like a photo bank). When someone opens the gallery and reaches the final gallery item from the first set, it looks like there are no more items.

I've added the logic to fetch next set of items (html) when last slide is displayed, but can't load them in opened gallery. The user would have to close the gallery and reopen it for every set of new images.

siovene commented 2 years ago

@fancyapps: I'm also interested in the same feature. As @zub0r, I have a page with some image thumbnail, and if the user scrolls down, more are loaded. However, I would like that when the user opens the Fancybox gallery view, and reaches the last image, more images are loaded with AJAX and appended to the current Fancybox instance.

Is there a way to achieve this? Thanks!

fhnb16 commented 1 year ago

Good idea, waiting for this feature too :)

fancyapps commented 1 year ago

Hi,

Starting from v5, you can add new slides like this:

Fancybox.getInstance().carousel.appendSlide({ src : "https://lipsum.app/id/1/800x600", type: "image"});

However, currently the thumbnails are not synchronized, but this is planned to be implemented.

Container-Zero commented 1 year ago

你好,

从 v5 开始,您可以像这样添加新幻灯片:

Fancybox.getInstance().carousel.appendSlide({ src : "https://lipsum.app/id/1/800x600", type: "image"});

不过,目前缩略图尚未同步,但计划实施。

Looking forward to adding thumbnail synchronization function.

fancyapps commented 10 months ago

As of v5.0.25, it is possible to create a gallery with an infinite number of items, and thumbnails are synchronized.

Here are two possible solutions.

1. Solution

Add new slides as the user nears the end of the gallery while navigating.

const addSlides = () => {
  const carousel = Fancybox.getInstance()?.carousel;
  const totalSlides = carousel?.slides.length || 0;
  const requiredSlides = Math.ceil(window.innerWidth / 96);

  if (carousel && carousel.page >= totalSlides - requiredSlides) {
    carousel.appendSlide({
      src: `https://lipsum.app/id/${totalSlides + 1}/1024x768/`,
      thumb: `https://lipsum.app/id/${totalSlides + 1}/300x225/`,
      caption: `#${totalSlides + 1}`,
    });

    addSlides(carousel);
  }
};

Fancybox.bind('[data-fancybox="gallery"]', {
  Carousel: {
    infinite: false,
  },

  on: {
    "Carousel.ready": () => {
      addSlides();
    },
    "Carousel.change": () => {
      addSlides();
    },
  },
});    

https://jsfiddle.net/d17qftax/

2. Solution

In the previous solution, you'll notice that even though the main carousel is infinite, the user can reach the end of the row of thumbnails. The solution would be to add new slides when the thumbnail carousel position is changed.

const addSlide = () => {
  const carousel = Fancybox.getInstance()?.carousel;

  if (carousel) {
    const totalSlides = carousel.slides.length;

    carousel.appendSlide({
      src: `https://lipsum.app/id/${totalSlides + 1}/1024x768/`,
      thumb: `https://lipsum.app/id/${totalSlides + 1}/300x225/`,
      caption: `#${totalSlides + 1}`,
    });
  }
};

Fancybox.bind('[data-fancybox="gallery"]', {
  Carousel: {
    infinite: false,
  },

  Thumbs: {
    Carousel: {
      on: {
        "refresh Panzoom.afterTransform": (carousel) => {
          const { viewportDim, contentDim, panzoom } = carousel;
          const currentPos = (panzoom?.current.e || 0) * -1;

          if (contentDim - viewportDim - currentPos < viewportDim * 0.5) {
            addSlide();
          }
        },
      },
    },
  },
});   

https://jsfiddle.net/nom5p2u7/