Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serving images of unknown size - suggestion/solution #796

Open
gincius opened this issue Mar 26, 2015 · 31 comments
Open

Serving images of unknown size - suggestion/solution #796

gincius opened this issue Mar 26, 2015 · 31 comments

Comments

@gincius
Copy link

gincius commented Mar 26, 2015

How to serve images with unknown size - my solution:

var items = [ 
  { src: 'http://........', w:0, h:0 },
  { src: 'http://........', w:0, h:0 }
];

var gallery = new PhotoSwipe( ..... );
gallery.listen('gettingData', function(index, item) {
        if (item.w < 1 || item.h < 1) { // unknown size
        var img = new Image(); 
        img.onload = function() { // will get size after load
        item.w = this.width; // set image width
        item.h = this.height; // set image height
           gallery.invalidateCurrItems(); // reinit Items
           gallery.updateSize(true); // reinit Items
        }
    img.src = item.src; // let's download image
    }
});

gallery.init();
@dimsemenov
Copy link
Owner

Nice, thx for sharing.

#741

@willyguevara
Copy link

+1

@renet
Copy link

renet commented May 8, 2015

Could it be that opening "zoom-in" animations don't work with this solution?

@dimsemenov
Copy link
Owner

@renet, as the animation runs instantly. It's not possible to execute it when final coordinates are unknown (0,0).

@pie6k
Copy link

pie6k commented May 17, 2015

Is it possible then to wait for 'zoom-in' until image is loaded and size is known?

@dimsemenov
Copy link
Owner

@AdamPietrasiak, sure, preload image, find its size and only then initialize PhotoSwipe. But you'll need to handle progress indication by yourself.

@sk29110
Copy link

sk29110 commented Jul 23, 2015

Just question why you need the width and height? Usually all other lightbox plugins doesn't requre the width and height. Is this for zoom in and out feature?

@dimsemenov
Copy link
Owner

@sk29110, http://photoswipe.com/documentation/faq.html#image-size

@sk29110
Copy link

sk29110 commented Jul 24, 2015

Thanks.
Just for interest and save time to save the width and height on database, I tried the @gincius 's solution by putting gallery.updateSize on image load. It seems going to the loop so the browser is frozen. His solution won't work for latest version(4.1.0)? I am trying with google chrome on mac.

@mjau-mjau
Copy link

Nice fix, thnx. A good fallback solution when exposing photoswipe for usage in custom html content.

@mjau-mjau
Copy link

Just a quick addition to @gincius code, which might solve the issue for @sk29110 also. I noticed that gettingData triggers continuously, likely while images are being loaded? This is what I see in console for a 3-slide object:

screen1

This also means that the img.onload will be triggered multiple times for the same images, causing unnecessary invalidateCurrItems() and updateSize(true) being triggered, which could cause havoc. The simple solution is to add a flag item.onloading:

// Make sure the slide is not html, and that the onLoad was not already triggered for this item
if(item.html === undefined && item.onloading === undefined && (item.w < 1 || item.h < 1)) {
  item.onloading = true;

Although the gettingData listener still triggers, the img.onload will only trigger once per image:

screen2

@jamminjames
Copy link

I seems that this only works with the history setting set to history:false, correct?

@mjau-mjau
Copy link

I seems that this only works with the history setting set to history:false, correct?

I tested, and it works fine with history. No reason it shouldn't, as the function is entirely unrelated.

@ghost
Copy link

ghost commented Sep 27, 2015

Other solution: if you get items by querying from database, after getting image size you can store/update w and h field into database. Next client will get image size from database instead of getting data from browser

@mjau-mjau
Copy link

@yudaprama good. But if you are querying the database, aren't you also using a server-side language that can simply read the image dimensions instead?

@ghost
Copy link

ghost commented Jan 8, 2016

I was originally adding the size data attributes in after they loaded then trying to insert them into the items array but I found this a much better solution and works for me. Thanks for sharing I was about to ditch this when I realized it had to have the image sizes, there's gotta be a way to work this in

@nkpz
Copy link

nkpz commented Aug 11, 2016

Thanks for this one. Didn't realize how much manual work was involved in init'ing PhotoSwipe and was getting worried for a sec.. this makes it usable for me! Would be nice if this kind of functionality were optionally baked in

@mmillet
Copy link

mmillet commented Oct 28, 2016

It works, Thanks!

@JoDring
Copy link

JoDring commented Nov 7, 2016

@mjau-mjau use the event 'imageLoadComplete' instead of 'gettingData' work for me.

@walenzack
Copy link

@mjau-mjau The reason for the multiple gettingData events (and the flickering it causes) is the call to invalidateCurrItems() inside @gincius code (great work btw! thanks a lot!), which is actually not necessary.
That call invalidates all loaded items in the array (visible an preloaded); but we just need to refresh one item and, in fact, just calling updateSize(true) is enough:

pswpGallery.listen('gettingData', function (index, item) {
    if (item.w < 1 || item.h < 1) {
        var img = new Image();
        img.onload = function () {
            item.w = this.width;
            item.h = this.height;
            pswpGallery.updateSize(true);
        };
        img.src = item.src;
    }
});

Just by removing that function call, the flickering and redundant background calls to gettingData are gone.

I tried the item.onloading = true approach too, but I run into some kind of problem (can't remember right now) so I had to dig deeper and came up with the above solution.

I've extensively tested it with single- and multiple-image galleries in Firefox, Chrome, IE11 and Edge desktop browsers, and Firefox (Android), Safari (iPhone / iPad) and Chrome (both systems) mobile browsers. Images of unknown size are correctly resized and displayed in all of them. Hope it helps.

@tscislo-lingaro
Copy link

@walenzack
Unfortunately when I removed invalidateCurrItems() I stil get redraw of currently visible image, with flickering and zoom is reset.

@gnodiah
Copy link

gnodiah commented Jun 22, 2017

@gincius @mjau-mjau thx u guys, great works!

@PoeHaH
Copy link

PoeHaH commented Jun 29, 2017

All solutions provided here didn't work for me. Causes the browser to crash (endless loop I assume).

@mjau-mjau
Copy link

@PoeHaH That would be something with your code unrelated to the code here. This code is being used for 100s of websites already, and you can see a demo here, which works in all browsers:
https://demo.imagevuex.com/examples/plugins/popup/

If you post an example of your code on Codepen, I would be happy to take a look.

@PoeHaH
Copy link

PoeHaH commented Jun 29, 2017

@mjau-mjau Thanks for your quick reply! In the meantime, I fixed it by just preloading the images and setting width/height outside of the 'gettingData' event.

@kaisermann
Copy link

kaisermann commented Aug 30, 2017

A slightly modified version of the previous code to use the thumbnail image size (assuming a more or less equal image ratio) as a initial fallback:

Ps: my item has a el property denoting its relative HTMLElement

pswpGallery.listen('gettingData', (index, item) => {
  if (!item.w || !item.h) {
    const innerImgEl = item.el.getElementsByTagName('img')[0]
    if (innerImgEl) {
      item.w = innerImgEl.width
      item.h = innerImgEl.height
    }

    const img = new Image()
    img.onload = function () {
      item.w = this.width
      item.h = this.height
      pswpGallery.updateSize(true)
    }
    img.src = item.src
  }
})

@YuJieun
Copy link

YuJieun commented Jul 31, 2018

thank you very very much

@xariketi
Copy link

Hello! I'm trying to implement this method on this codepen example without success :

https://codepen.io/alienlebarge/pen/Kdrxga

Can someone implement it?

@arammarm
Copy link

You can use this to fix it.. Give any value you want for h and w and add

.pswp img {
    max-width: none;
    object-fit: contain;
}

above css

@darko-r
Copy link

darko-r commented Nov 22, 2020

My solution, maybe helps someone: link

@mikelgmh
Copy link

mikelgmh commented Jun 21, 2023

This is my solution:

Create a function that sets the pswp-width and pswp-height attributes to the anchors before initializing the PhotoSwipe gallery. We need to wait until all the images have been loaded, and we're using promises for this.

async function prepareImagesForPhotoswipe() {
    // Get the <a> tags from the image gallery
    const imagesList = document.querySelectorAll(".image-masonry__item a");
    const promisesList = [];
    imagesList.forEach((element) => {
        const promise = new Promise(function (resolve) {
            let image = new Image();
            image.src = element.getAttribute('href');
            image.onload = () => {
                element.dataset.pswpWidth = image.width;
                element.dataset.pswpHeight = image.height;
                resolve(); // Resolve the promise only if the image has been loaded
            }
            image.onerror = () => { resolve(); };
        });
        promisesList.push(promise);
    });
    // Wait for all promises to be resolved
    await Promise.all(promisesList);
}

// Call the function using await
await prepareImagesForPhotoswipe();

// Now initialize the lightbox:
const lightbox = new PhotoSwipeLightbox({
    gallery: '.image-masonry',
    children: '.image-masonry__item a',
    showHideAnimationType: 'zoom',
    showHideOpacity: true, 
    showAnimationDuration: 200,
    pswpModule: photoswipe
});

lightbox.init();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests