dimsemenov / PhotoSwipe

JavaScript image gallery for mobile and desktop, modular, framework independent
http://photoswipe.com
MIT License
24.18k stars 3.31k forks source link

Getting started improvement #1616

Open KingSora opened 5 years ago

KingSora commented 5 years ago

Good day!

Today I came across this library, and the initialization process is very different from all the other lightbox plugins I've tested out. It was also kinda deterrent for me that I have to provide the image dimensions by myself (as mentioned here).

After testing I've to admit: this library is very very good. So I've worked out a example which could help potential new users to overcome the troubles of the initialization process.

In my application I'm working with jQuery, so I've implemented this whole example as a jQuery extension.

(function ($) {
  var imgCache = [ ];
  var getCache = function(src) {
    var result;
    $.each(imgCache, function(index, value) {
      var cacheObj = value;
      if(cacheObj.src === src) {
        result = cacheObj;
        return false;
      }
    });
    return result;
  };
  var updateCache = function(src, w, h) {
    var cache = getCache(src);
    if(!cache) {
      imgCache.push({
        src : src,
        w : w,
        h : h,
      });
    }
    else if(cache.w !== w || cache.h !== h) {
      cache.w = w;
      cache.h = h;
    }
  };
  $.fn.photoSwipe = function(options, galleryParent) {
    var openPhotoSwipe = function(index, galleryItems) {
      var photoSwipeItems = [ ];
      var refItems = [ ];
      galleryItems.each(function() { 
        var galleryElm = $(this);
        var linkElm = galleryElm.is('a') ? galleryElm : galleryElm.find('a');
        if(linkElm) {
          var imgElm = linkElm.find('img')[0];
          var imgSrc = linkElm.attr('href');
          var cache = getCache(imgSrc);
          photoSwipeItems.push(cache 
            ? {
              src : cache.src,
              w : cache.w,
              h : cache.h
            } 
            : { 
              src : imgSrc,
              w : 0,
              h : 0
            }
          );
          refItems.push({ 
            img : imgElm,
          });
        }
      });
      gallery = new PhotoSwipe($('.pswp')[0], PhotoSwipeUI_Default, photoSwipeItems, $.extend(true, options, {
        index : index
      }));
      gallery.listen('gettingData', function(index, item) {
        if (item.w < 1 || item.h < 1) {
          var cache = getCache(item.src);
          if(cache) {
            item.w = cache.w;
            item.h = cache.h;
            gallery.invalidateCurrItems();
          }
          else {
            updateCache(item.src, 0, 0);

            var img = new Image(); 
            img.onload = function() {
              item.w = this.width;
              item.h = this.height;

              updateCache(item.src, item.w, item.h);

              gallery.invalidateCurrItems();
              gallery.updateSize(true);

              img = null;
            }
            img.src = item.src;

          }
        }
      });

      gallery.listen('imageLoadComplete', function(index, item) { 
        updateCache(item.src, item.w, item.h);
      });

      gallery.init();
    };
    var passedGalleryItems = this;

    return this.each(function() {
      var elm = $(this);
      elm.on('click', function(e) {
        e.preventDefault();
        var target = $(e.currentTarget);
        var parent = galleryParent && galleryParent instanceof $ ? target.closest(galleryParent) : undefined;
        if(!parent)
          parent = $(target.parent());
        var galleryItems = parent.find(passedGalleryItems);
        var index = galleryItems.index(target);
        if(index > -1)
          openPhotoSwipe(index, galleryItems);
        return false;
      });
    });
  };
})(jQuery);

With this snipped the initialization process is as easy as:

$(".myGallery > .myGalleryImage").photoSwipe({
  bgOpacity : 0.9
});

A example fiddle can be found here.

I've also implemented a option to define the gallery element, per default its the parent element of the clicked element:

$(".myGallery > .myGalleryImage").photoSwipe({
  bgOpacity : 0.9
}, $("body"));

A example fiddle can be found here, the difference from the above example is, you don't really have really 2 galleries, but one big with 7 items, because the gallery element is the body.

I've also managed to implement a automated image size detection (with cache) which does a pretty okay job and isn't as ressource hungry as in #741 or #796 because of the mentioned cache system.

You could also implement something like this (maybe even without jQuery as it is only a tool and dont really required here) on the getting started page for people which aren't as experienced in javascript or just want a "quick and dirty" initialization.

cylott commented 4 years ago

Thank you very much for this

cylott commented 4 years ago

Hi @KingSora, I wanted to thank you again for your work on this. I've implemented on a number of sites and I have to say it is a huge advantage to be able to define the image dimensions dynamically this way.

One thing I've noticed though is that there seems to be some flickering issues when switching between slides. The image will flash blank and then load. This doesn't seem to happen when I supply all the dimensions the old way. Any ideas what might be causing this?

KingSora commented 4 years ago

@cylott good question... since I wrote this quite some time ago I don't remember the exact details and whether there is a issue with the code from me. I'm sorry I can't help.

prohtex commented 4 years ago

Could this script be modified to read captions from an img "data-caption" tag?