javascriptphotoswipe

Photoswipe 4.0: Initiate 'swipe to next' programatically


SITUATION

I have been trying to trigger the 'slide to next picture' animation when the NEXT button is clicked, but i have not found a solution for this.

There is an ongoing discussion about this on GitHub, but it is only about adding the option for a slide animation, not about how to actually do it with PS as it is right now.

There was an option for it in 3.0 but as 4.0 is a complete rewrite it does not work anymore.

QUESTION

Instead of just 'jumping' to the next/prev picture when an arrow is clicked, i need the 'slide transition' that is also used when swiping/dragging the image.

There is no option to trigger that, so how can i manually trigger this effect with JS?


Solution

  • I finally bit the bullet and spent some time making this work as nobody seemed to have a solution for that, not here neither on GitHub or anywhere else.

    SOLUTION

    I used the fact that a click on the arrow jumps to the next item and triggers the loading of the next image and sets the whole slide state to represent the correct situation in an instant. So i just added custom buttons which would initiate a slide transition and then triggered a click on the original buttons (which i hid via CSS) which would update the slide state to represent the situation i created visually.

    1. Added NEW next and prev arrows
    2. Hid the ORIGINAL next and prev arrows via css
    3. Animated the slide myself when the NEW next or prev arrows were clicked
    4. Then triggered the click on the ORIGINAL next or prev arrows programmatically

    So here is the code:

    HTML

    // THE NEW BUTTONS
    <button class="NEW-button-left" title="Previous (arrow left)">PREV</button>
    <button class="NEW-button-right" title="Next (arrow right)">NEXT</button>
    
    // added right before this original lines of the example code
    <button class="pswp__button pswp__button--arrow--left ...
    

    CSS

    pswp__button--arrow--left,
    pswp__button--arrow--right {
      display: none;
    }
    NEW-button-left,
    NEW-button-right {
      /* whatever you fancy */
    }
    

    JAVASCRIPT (helper functions)

    var tx = 0; // current translation
    var tdir = 0;
    var slidepseactive = false;
    
    // helper function to get current translate3d positions 
    // as per https://stackoverflow.com/a/7982594/826194
    function getTransform(el) {
      var results = $(el).css('-webkit-transform').match(/matrix(?:(3d)\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))(?:, (-{0,1}\d+)), -{0,1}\d+\)|\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))\))/)
      if(!results) return [0, 0, 0];
      if(results[1] == '3d') return results.slice(2,5);
      results.push(0);
      return results.slice(5, 8);
    }
    
    // set the translate x position of an element
    function translate3dX($e, x) {
      $e.css({
        // TODO: depending on the browser we need one of those, for now just chrome
        //'-webkit-transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
        //, '-moz-transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
        'transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
      });
    };
    

    JAVASCRIPT (main)

    // will slide to the left or to the right
    function slidePS(direction) {
      if (slidepseactive) // prevent interruptions
        return;
    
      tdir = -1;
      if (direction == "left") {
        tdir = 1;
      }
    
      // get the current slides transition position
      var t = getTransform(".pswp__container");
      tx = parseInt(t[0]);
    
      // reset anim counter (you can use any property as anim counter)
      $(".pswp__container").css("text-indent", "0px");
    
      slidepseactive = true;
      $(".pswp__container").animate(
        {textIndent: 100},{
          step: function (now, fx) {
            // here 8.7 is the no. of pixels we move per animation step %
            // so in this case we slide a total of 870px, depends on your setup
            // you might want to use a percentage value, in this case it was
            // a popup thats why it is a a fixed value per step
            translate3dX($(this), tx + Math.round(8.7 * now * tdir));
          },
          duration: '300ms',
          done: function () {
            // now that we finished sliding trigger the original buttons so 
            // that the photoswipe state reflects the new situation
            slidepseactive = false;
            if (tdir == -1)
              $(".pswp__button--arrow--right").trigger("click");
            else
              $(".pswp__button--arrow--left").trigger("click");
          }
        },
        'linear');
    }
    
    // now activate our buttons
    $(function(){
    
      $(".NEW-button-left").click(function(){
        slidePS("left");
      });
    
      $(".NEW-button-right").click(function(){
        slidePS("right");
     });
    
    });
    

    I used info from those SE answers: