dimsemenov / PhotoSwipe

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

The next major release and the project status (your feedback needed) #1749

Open dimsemenov opened 3 years ago

dimsemenov commented 3 years ago

Demo and docs for the new version

Hi all,

I'd like to share an update on the PhotoSwipe development. And I need your feedback.

Code rewrite and quality

I rewrote everything to modern JavaScript, it should now be easier to contribute or extend. Total JS file size is reduced by about 15%. The code is published in v5-beta branch (src/ for source files, dist/ for compiled files).

Skinning

PhotoSwipe no longer requires an external sprite and has only a single CSS file. Default icons are generated via JavaScript and are very small. Minor styling can be done via CSS variables.

I designed the new icons so they're visible on the dark and light background without having a dark backdrop:

Frame 3icons

A new guide on how to use your own icons →

Initialization

As you probably know, the current PhotoSwipe initialization is quite a mess, I'm trying to fix this problem.

In the new version, you're no longer required to include HTML structure for the lightbox itself.

The new version is split into two components, the second is loaded only after user initiates opening, so basic initialization looks like this:

<script type="module">
import PhotoSwipeLightbox from '/v5/photoswipe/photoswipe-lightbox.esm.js';
const options = {
  gallerySelector: '.gallery',
  childSelector: 'a',
  pswpModule: '/v5/photoswipe/photoswipe.esm.js',
};
const lightbox = new PhotoSwipeLightbox(options);
lightbox.init();
</script>

More info about what this code does here.

Obviously, such initialization is optional, and you can just include files via script src.

Animations

Opening from cropped thumbnail

PhotoSwipe is now able to animate from the cropped thumbnail. Test it →

Animation4

Opening image in a zoomed state

It's now easier to control the initial zoom level, Test it →.

Reponsive images

You may now define srcset for images inside the lightbox.

PhotoSwipe now automatically generates and updates sizes attribute depending on zoom level.

Features that will likely be removed:

You may now support PhotoSwipe on OpenCollective

I've lost motivation and abandoned the project for a year. I'm trying to find a way to prevent this from happening in the future and keep PhotoSwipe free and open-source.

I've created an OpenCollective account, consider sponsoring PhotoSwipe development. To give something in return I will provide email support for sponsors, so you may ask any question if you're having a problem.


If you have a minute, please test demos for v5 Beta on your mobile device, report issues via GitHub, or just email me.

markfinst commented 3 years ago

New demos look great, when do you plan to release it? Or can I use it in project now?

dimsemenov commented 3 years ago

@markfinst I wouldn't recommend using it in production for now.

PeterSweetAndSour commented 3 years ago

Although Opera Mini is not supposed to work, it seems to perform just fine on the demos on https://photoswipe.com/v5/docs/getting-started/. I am happy about this because that is my default mobile browser (Android, current version is 55.1.2254.56965) but CanIUse does show "all" versions do not support ES6 modules.

I am happy to see that closing on scrolling is going away because I will eventually get back to my quest of making a version that allows scrolling for long captions. I had to override it for my interim solution for my own site where the extended caption slides up from the bottom. https://github.com/dimsemenov/PhotoSwipe/issues/1692

Thank you for the improved images that work on dark or pale backgrounds. I see now harm in removing the share options since the URL is all that is needed.

fedyd commented 3 years ago

Hi,

I remember that when I used the previous version of your (great) plugin, I had troubles trying to implement also gesture for mobile devices. Will these be included in the new version? And will they maybe be usable for photo and video/doc/pdf/etc. as well? Thank you!

dimsemenov commented 3 years ago

@fedyd I want to keep the library slim, so video/doc/pdf will unlikely be supported by the core. It should be possible to implement via API though.

GoudekettingRM commented 3 years ago

Hi @dimsemenov ,

I'm so happy to read this and look through the demos. I'll have a closer look this weekend, but from what I've seen it is really impressive. Cannot wait to try it out a little.

fedyd commented 3 years ago

@dimsemenov thank you. got it!

benstechlab commented 3 years ago

Great to see a fresh start on PhotoSwipe! I'll give it a test in a side project while its in beta...

roelvan commented 3 years ago

Just tried the beta branch out in a vite.js powered app. So far so good! Will let you know in case I run into any problems. Thanks a lot for this update!

mjau-mjau commented 3 years ago

Great to see progress on V5 👌 Although somewhat outdated, Photoswipe 4 was still one of the best "popup" options for images. I spent some time myself modernizing the core and interface, which can be seen here: https://embed.photo.gallery/

Following with great interest.

Firsh commented 3 years ago

What's the reason behind ditching history API and social sharing/deeplinking?

dimsemenov commented 3 years ago

What's the reason behind ditching history API and social sharing/deeplinking?

History API is removed because of inconsistent behavior across different routing systems (such as Turbolinks), it also pollutes the user browser history in some cases (which makes back/forward browser actions unpredictable).

And Sharing API is removed as it forces you to load JS library right away, which is non-ideal in terms of page load speed. It also just doesn't work if the browser isn't supported. And Open Graph data is incorrect when just #hash is used, so when an image is shared via Facebook - the preview thumbnail is invalid.

evenreven commented 3 years ago

This looks extremely promising. I'm refactoring my entire application frontend now (Rails/Sprockets/jquery to Rails/webpack/vanilla-js/Stimulus) and I'm struggling with Photoswipe because of an old and opaque jquery initializer script, and thinking maybe I should just make the jump to v5 to avoid the extra work.

Getting this to work seems to take minimal effort unless you're doing something crazy. I'm a novice, and I got it to work with Rails with responsive images and captions in fifteen minutes with a working backend. In contrast, getting a barely working refactored v4 setup up and running took me hours and hours, and that wasn't even with responsive images (not the fault of v4 per se, my old setup was hard to parse). Great work lowering the barrier to entry, a lot of people will appreciate this! (And thanks for writing thorough examples, I never would have got captions to work otherwise.) I will test more the coming days to look for surprising behaviour (or bugs).

One thing, though: Maybe I'm dense, but can I integrate the examples with a bundler like webpack? The main problem is the inclusion of the pswpModule core (and css) via the options as URL and not through, say, an import statement. Using the webpack path obviously doesn't work, since node_modules isn't a public path. I've put the whole Photoswipe dist folder in my public path for now, but would like to serve it from node_modules if I can (instead of using a separate script tag). If importing the core module and the css is possible, it's easier to help with testing transpiling as well. If that's a goal for you, that is!

ghost commented 3 years ago

To be honest the "Native fullscreen button" is one of the pros on photoswipe please try not to remove it

I use full screen option more often then the zoom in button not sure what other people's opinion on this but this is my use case.

going directly to full screen is great but it is not good for accessibility which is becoming more and more important everyday. instead of directly opening full screen it will be nice to provide option to choose when and if user wants full screen

thanks

Cube707 commented 3 years ago

Should the options work allready or are the work in progress? I tried changing the backgound opacity and broke it.
(static website, copy-pasted your code, worked untill i added more stuff into the options array)

Liking the update so far. really good work

dimsemenov commented 3 years ago

@Cube707 documented options should work, how exactly are you modifying it? It must be a number between 0 and 1. Please open a separate issue if you won't be able to resolve the problem.

@john-gr there is an example with native fullscreen here - https://photoswipe.com/v5/docs/native-fullscreen-on-open/

Ambient-Impact commented 3 years ago

This looks awesome so far! I know how hard it can be to get stuff done like this with regards to motivation.

History API is removed because of inconsistent behavior across different routing systems (such as Turbolinks), it also pollutes the user browser history in some cases (which makes back/forward browser actions unpredictable).

Being able to close the viewer by hitting back feels really intuitive, and it stood out to me as a missing feature. That said, I understand the issues, and as long as the API is there to open/close the viewer and listen to events or callbacks, I'm fine with that.

ErnstWG commented 3 years ago

Hi. I am using Photoswipe together with JIG. Can I make it to integrate PS v5 beta with JIG? Background for this. I want to use the PS Lightbox in a full screen mode together with the titel/caption/UI elements. With v4 I couldn't get it to work, only with framing. Looking forward to your answer.

alekssskirov commented 3 years ago

I want to go to 5: Triggers https://github.com/kaisermann/PhotoSwippy#triggers

ghost commented 3 years ago

@Cube707 documented options should work, how exactly are you modifying it? It must be a number between 0 and 1. Please open a separate issue if you won't be able to resolve the problem.

@john-gr there is an example with native fullscreen here - https://photoswipe.com/v5/docs/native-fullscreen-on-open/

@dimsemenov going directly to full screen is great but it is not good for accessibility which is becoming more and more important everyday. instead of directly opening full screen it will be nice to keep the current functionality to let user choose when and if they wants full screen. some users might prefer some might not the current functionality of photoswipe is great why change it?

I strongly believe having the option to go full screen make life easier for user and developer as a developer I don't have to choose between making directly full screen or having no option of full screen and user can also click the full screen icon when they want that feature.

the option between choosing a forced fullscreen or no full screen is a really bad option I think and it is one of the pro of photswipe why remove the current setup?

thanks

picarica commented 3 years ago

will there be a proper support for html5 video and youtube and vimeo embeded videos ?

acwolff commented 3 years ago

Where can I download all code of a good example? I like to adapt that to my own requirements, but it is nice to start with a good working example. Thanks in avance!

hellomedia commented 3 years ago

Thank you @dimsemenov for this great lib and for your work on a v5.

I am excited about the cropped image animation and the responsive image support.

nitin2953 commented 3 years ago

because those are old and heavy

font ⇒ Google Sans 144x144

photoswipe.zip

floogulinc commented 3 years ago

This is very cool, I'm glad to see this is being worked on again. The ability to use dynamically generated data for a source is very nice but I am wondering if it can be made to also accept promises in the event callback. This would enable dynamically fetching data from the server for each slide.

11bits commented 3 years ago

Is it possible to install v5 via npm?

dimsemenov commented 3 years ago

@11bits not yet

ilyacuc commented 3 years ago

Hi! Nice work! Especially I like how smooth pinch-to-zoom works. I've played around with the new version and figured out that it is impossible to use the library with a modern bunder approach (e.g. webpack) because I have to pass pswpModule URL to the lightbox initializer. As a simple solution, I suggest adding an option to pass to the initializer module itself rather than its URL.

nlundquist commented 3 years ago

Is it possible to install v5 via npm?

not directly, but you can use the branch via: npm install --save git://github.com/dimsemenov/photoswipe#v5-beta

3zzy commented 3 years ago

Great, but still no RTL support :(

picarica commented 3 years ago

how about video support? i wish it would be easier in the new version

mallardduck commented 3 years ago

@dimsemenov - I've been playing around with this release and am having issues dynamic data sources. The main issue I'm having is that I can't seem to set the itemData based on an API call.

For instance I've tried using via Laravel livewire, Axios and plain XMLHttpRequest but the slide fails to load either way. The error seems to be about a placeholder, but I'm not able to figure out how I can control that to ensure there's a placeholder. See the error here:

Uncaught (in promise) TypeError: this._placeholder is undefined
    _initiate opener.js:211
    _start opener.js:199
    open opener.js:32
    init photoswipe.js:177
    _openPhotoswipe lightbox.js:232
    preload lightbox.js:187
    promise callback*preload lightbox.js:178
    loadAndOpen lightbox.js:129

UPDATE: So as mentioned I was using a handful of methods to try this and all of them used Async style GET requests. I finally considered going more "old school" and forcing the GET request to be synchronous. This was in fact able to sovle the issue. I was having above, however it'd be nice if things were more flexible for this use case.

The current "dynamic data source" example is rather trivial in that it only utilizes a single size of images and the image URLs and order are determined by a simple index. The real use cases for dynamic data sources won't be as simple as this though. In my case I've created an endpoint that returns JSON with info for a single slide - then it uses the index for the pagination's "page" value.

So the working solution was:

        pswp.on('itemData', (e) => {
            const { itemData } = e;

            var request = new XMLHttpRequest();
            request.open('GET', '{{ route('user.gallery.json', $user) }}?page=' + (e.index + 1), false);
            request.send(null);

            if (request.status === 200) {
                let parsed = JSON.parse(request.responseText);
                itemData.msrc = '{{ asset('placeholder.png') }}';
                itemData.src = parsed.data.src;
                itemData.w = parsed.data.w;
                itemData.h = parsed.data.h;
            }
        });

However it'd be cool if I could use the async based helpers that Livewire provides like:

        pswp.on('itemData', (e) => {
                const { itemData } = e;
                var results = @this.getItem(e.index + 1);
                var parsedPromise = results.then((result) => {
                    parsed = JSON.parse(result);
                    itemData.msrc = '{{ asset('placeholder.png') }}';
                    itemData.src = parsed.data.src;
                    itemData.w = parsed.data.w;
                    itemData.h = parsed.data.h;
                    return parsed;
                });
        });

Even if something like this would need to be wrapped a bit like:

        pswp.on('itemData', (e) => {
            var parsed = null;
            (async (e, parsed) => {
                const { itemData } = e;
                var results = @this.getItem(e.index + 1);
                var parsedPromise = results.then((result) => {
                    parsed = JSON.parse(result);
                    return parsed;
                });
                await parsedPromise;
                itemData.msrc = '{{ asset('placeholder.png') }}';
                itemData.src = parsed.data.src;
                itemData.w = parsed.data.w;
                itemData.h = parsed.data.h;
            })(e, parsed);
        });
guivr commented 3 years ago

I've tried different lightbox plugins and PhotoSwipe is THE BEST! Seriously guys huge congrats on your work, this is looking amazing! Can't wait to use it on React (no wrappers has the v5 yet). I'm using v4 (which is awesome too) on my website.

What I LOVE about v5:

Bug:

Feature suggestions:

emmahsax commented 3 years ago

I just set up PhotoSwipe for the first time on v5, and I'm really enjoying it! It's a very smooth user experience.

There's a couple pieces that I think are missing from the documentation, though.

The first is when adding captions, if you have some photos with captions, and some without (all within the same gallery), then the space for the caption doesn't disappear, even if the caption itself is empty. I've modified the documentation's suggested Javascript "plugin" in my implementation here.

The second is the ability to have nested galleries. So we could in theory have one large gallery, and then a nested gallery inside, and then a nested gallery inside that if we even wanted to. What the documentation doesn't really make clear is that this is possible. The trick is to initialize PhotoSwipe for each gallery, and use different gallerySelectors and childSelectors for each gallery.

But all-in-all, this was easy to set up and easy to use! If a javascript novice like me can do it, then you can, too!

BilouMaster commented 3 years ago

I am currently using LightGallery but have always been considering using PhotoSwipe for its smoothness, as a newbie I've simply had troubles setting up PS so I used LG... Now I am very glad to see you baking a 5th version and I will use it even if it's beta, for the sake of awesomness! :)

Demo is working like charm on my mobile phone (tested with chrome, firefox and firefox focus), there is just the first image on the "native fullscreen support" example that "could not be loaded", I don't know why.

Congratulation for making the best lightbox even better!!

EDIT: I am now using PhotoSwipe and I am the happiest man in the world 🔥 🥰

kaermorchen commented 3 years ago

Webpack by default replace import to it custom import and photoswipe will not work, because use browser's import. To resolve this add to webpack.config.js this lines:

return {
    module: {
      rules: [
        {
          parser: {
            import: false
          }
        },
...
BilouMaster commented 3 years ago

@john-gr comment

To be honest the "Native fullscreen button" is one of the pros on photoswipe please try not to remove it

I use full screen option more often then the zoom in button not sure what other people's opinion on this but this is my use case.

going directly to full screen is great but it is not good for accessibility which is becoming more and more important everyday. instead of directly opening full screen it will be nice to provide option to choose when and if user wants full screen

thanks

See my issue #1759 for a workaround 😃

ghost commented 3 years ago

@john-gr comment

To be honest the "Native fullscreen button" is one of the pros on photoswipe please try not to remove it I use full screen option more often then the zoom in button not sure what other people's opinion on this but this is my use case. going directly to full screen is great but it is not good for accessibility which is becoming more and more important everyday. instead of directly opening full screen it will be nice to provide option to choose when and if user wants full screen thanks

See my issue #1759 for a workaround 😃

This is a great workaround ready for anyone to use thanks @BilouMaster

jmory commented 3 years ago

@dimsemenov - First of, thank you for all the time and effort you put into this project, great work! We are happily using PhotoSwipe in our project for a few years now without any problems.

I tried to replace PhotoSwipe v4 with v5-beta in our project (just as a POC), but ran into a few issues. Since it's still a beta, I'd like to ask you, if you could clarify whether it still will be possible to use PhotoSwipe V5 as we currently do in production with V4:

When trying to switch to V5 beta I ran into following issues (I was using the core module, not the lightbox module, since we have our own custom lightbox):

Is this something you intentionally do not want to support in V5, or are those options just not implemented yet? Is it even intended to directly use the core module, without the lightbox module in V5?

I know that you can customize UI elements (https://photoswipe.com/v5/docs/styling/), and add custom buttons (https://photoswipe.com/v5/docs/adding-custom-buttons/), but this sacrifices some (IMO) nice benefits of being able to render a custom UI that is not tied to PhotoSwipe:

I'm aware that this is a free, open-source project. I don't feel entitled to anything, and I hope my post does not come off as if I do. If you envision PhotoSwipe V5 to support to still use it in a way outlined above, and I can contribute to make it happen, just let me know!

dimsemenov commented 3 years ago

@jmory thanks a lot for the feedback, I'll try explain:

About UI being a completely separate component

I understand that if you use something like Angular - you'd rather use Angular buttons. However, due to the nature of the PhotoSwipe, click/tap/drag events are handled in a special way and elements that are on top of the scrolling area are handled by the gallery.

Also, the v5 UI is tiny, so I don't see the point to separate it from the core.

You still can add any elements on top of PhotoSwipe, but they'll block gestures unless you either pointer-events: none or append within pswp__scroll-wrap.

v5 indeed lacks documentation on how to disable UI elements, I'll try to improve this in the future patch. Currently, UI elements are just disabled by name, for example (arrowPrev:false, zoom:false, close:false).

Inline gallery

The experimental modal option that allowed to use PhotoSwipe as a simple carousel is no longer available. If you just need a carousel - consider using a native overflow-x scroller with -webkit-overflow-scrolling: touch or any "slider" component.

v5 browser support range is much narrower and it's mainly designed to be used as a "lightbox" component.

appendToEl option

By default PhotoSwipe is added within document.body, this option allows to append it to some different element. It does not affect viewport size, as viewport size is measured not by parent element (because of mobile toolbars that are quite inconsistent).

If you're looking to add a custom sidebar you may use padding options. For example paddingRight: 200 will add 200px gap on the right side.

You may also use option getViewportSizeFn (default implementation is here), for example:

getViewportSizeFn: () => {
  return {
    x: document.documentElement.clientWidth - 200,
    y: window.innerHeight
  };
}
robertmaier commented 3 years ago

@dimsemenov The Browser Support part of the documentation contains a link to caniuse which just triggers a search for module, so It' s not 100% clear which part of the modules specification is a requirement for V5.

Is it the ECMAScript 2015 Spec, which is includes support for Modules (https://caniuse.com/es6) or is it Dynamic imports (https://caniuse.com/es6-module-dynamic-import)?

Both differ quite a bit when it comes to supported browser versions.

dangelion commented 3 years ago

@dimsemenov What an awesome news! 🎉

Since I install Photoswipe via npm I'm having difficulties to import it. I opened a question here: https://github.com/dimsemenov/PhotoSwipe/issues/1763 Any help? @evenreven @ilyacuc @nlundquist

@dimsemenov Is it in plan to add "support" for npm/Webpack-like environment? It's a keypoint for many in the choice of this library.

Just one little note aside: please keep that amazing behaviour that scrolling down it closes the lightbox. Consider that many mainstream websites and apps have that, so it's popular UX for users.

evenreven commented 3 years ago

What's the reason behind ditching history API and social sharing/deeplinking?

History API is removed because of inconsistent behavior across different routing systems (such as Turbolinks), it also pollutes the user browser history in some cases (which makes back/forward browser actions unpredictable).

I was browsing through a series of pictures in a WhatsApp thread, and the back button closes the lightbox view, as is the custom on Android. Since the Photoswipe animation and general layout is pretty similar to WhatsApp's (it also has swipe down to close), muscle memory made me try the back button on my new v5 beta lightbox, and it of course went all the way to a different page. I don't think WhatsApp (or Google Photos, which behaves similarly) should decide what Photoswipe is like, but I would argue that not having back button close the lightbox violates the principle of least surprise, at least on Android where it's common to press the back button a lot because of its global design.

When it comes to Turbo(links), I'm using it, and I already have plenty of workarounds for history weirdness. 😉 "How do I make Turbo work with this component which uses pushState/replaceState" is probably the single most frequently asked question on the Turbo(links) issue trackers and the Hotwire forums. Meaning: I don't think you should remove this just because it doesn't work with Turbo out of the box. We're used to it. Just turn history off by default, and no one will complain. 😉

BTW, my preferred way of handling history would be to use pushstate when opening the lightbox, and replacestate when using next/previous. That way there will be less pollution of history, and the back button will always close the lightbox instead of showing the previous image. This is in line with Android convention (and, in my opinion, good UX design). Just a thought!

prohtex commented 3 years ago

This looks awesome so far! I know how hard it can be to get stuff done like this with regards to motivation.

History API is removed because of inconsistent behavior across different routing systems (such as Turbolinks), it also pollutes the user browser history in some cases (which makes back/forward browser actions unpredictable).

Being able to close the viewer by hitting back feels really intuitive, and it stood out to me as a missing feature. That said, I understand the issues, and as long as the API is there to open/close the viewer and listen to events or callbacks, I'm fine with that.

@dimsemenov For me the ability to open the viewer from a unique URL is crucial, is that preserved without the history API?

prohtex commented 3 years ago

When it comes to Turbo(links), I'm using it, and I already have plenty of workarounds for history weirdness. 😉 "How do I make Turbo work with this component which uses pushState/replaceState" is probably the single most frequently asked question on the Turbo(links) issue trackers and the Hotwire forums. Meaning: I don't think you should remove this just because it doesn't work with Turbo out of the box. We're used to it. Just turn history off by default, and no one will complain. 😉

I agree with this completely. Will definitely miss History API!

Ambient-Impact commented 3 years ago

As much as I agree that the UX of having the History API is way better than not, I think it may also work out well if that's handled by a separate package or plug-in, so that people who want to use it can and it won't cause issues in PhotoSwipe core.

amkdev commented 3 years ago

After lightGallery, fancybox 4 I'm here now, because both very well known lightboxes uses a zoom functionality that blurring images because they use css scale calculations (>1) to zoom to natural size. That's ok for desktop but on mobile it is unacceptable. only the fancybox 4 developer saw a bigger problem in this .... but the way PhotoSwipe it does is the only right one. Perfectly sharp images.

The big con of PhotoSwipe is the unusual way to include it. I’m working with laravelmix/webpack and I can’t get it work in my bundled js. So I have to implement it separately.

Another not so nice thing are some frontend developer things. For instance: why is the background opacity a js option, although this could be better placed in the css file. Or why the icons images are an js option too? They should be defined in the css file too.

But it’s ok - I can live with that atm. Really nice would be a soft fade between slides. it feels unusual incomplete that images are opened via a nice transition and swapping from image to image is totally basic.

Thanks for your work and I look forward for improvements.

dimsemenov commented 3 years ago

I’m working with laravelmix/webpack and I can’t get it work in my bundled js

I agree that's it's the issue, and I'll improve this part before the release. For now, while it's in beta, you may import it like this https://github.com/dimsemenov/PhotoSwipe/pull/1764#issuecomment-867453153

For instance: why is the background opacity a js option

Background is a JS option because it's animated and changed via JS (for stuff like close on vertical drag). And I can't use rgba as it's not performant in some mobile browsers (comparing to just opacity).

Ambient-Impact commented 3 years ago

Background is a JS option because it's animated and changed via JS (for stuff like close on vertical drag). And I can't use rgba as it's not performant in some mobile browsers (comparing to just opacity).

Would it be possible to have the JavaScript set and update a CSS custom property? That way you can control it from JavaScript, but allow more customizability in third-party stuff. You could name it something descriptive like --photoswipe-close-factor (as it's a number from 0 to 1 that describes how closed PhotoSwipe is at that moment).

You could then in the PhotoSwipe stylesheet(s) just have opacity: var(--photoswipe-close-factor); and you could then use it in third-party code do all sorts of things; for example, if you wanted to translate a UI element more and more off-screen as the PhotoSwipe state is changed by user swiping down, you could do transform: translateY(calc(100% * var(--photoswipe-close-factor)));

See

dimsemenov commented 3 years ago

@Ambient-Impact that will likely trigger the style calculations on each frame, which will hurt performance.