简体   繁体   中英

Add image swipe support for mobile touch devices to Shadowbox.js

I'm using Shadowbox.js (web-based viewer like lightbox ) on various websites and it works great so far. The only problem is the bad support for mobile devices.

It is not possible to change images within the galery by swiping the current image, so the user have to use the very small navigation buttons at the bottom of the viewer-viewport. (keyboard navigation is also possible, but not on mobile devices)

It's not just the difficult usage of these navigation buttons. Every tap on the navigation button triggers a zoom function with a detail view of the focused area - and a second tap is needed to confirm the switch to the next or previous image.

It would be great, if it would be possible to make the galery behave like the default android galery viewer or similar mobile apps.

I'm using the jquery version of shadowbox.

There's an example script how to improve Shadowbox.js:

移动设备上的Shadowbox.js图像滑动

First you need the jQuery version of Shadowbox.js. Also jQuery UI is required and the jQuery UI Touch Punch plugin (size: 584 bytes). Without Punch-plugin jQuery UI does not support touch events.

  1. Add the required libraries if not already done:

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script> 

  1. Now we have to look at the required default- <script> -area of Shadowbox.js:

 <link rel="stylesheet" type="text/css" href="plugins/shadowbox-3.0.3/shadowbox.css"> <script type="text/javascript" src="plugins/shadowbox-3.0.3/shadowbox.js"></script> <script type="text/javascript"> Shadowbox.init( { onOpen: function() { }, players: ['html','img', 'iframe' ,'inline'] } ); </script> 

This is the minimum javascript call to initialize the Shadowbox.js viewer. onOpen is one of the events, which allows to run code at a specific point. In our case it's required to use a event, which is fired after loading the enlarged image. We use the event onFinish and run custom jQuery UI Code to make the image viewport of the viewer draggable to the x-axies.

So the user is able to drag the image from left to right or vice versa:

<script type="text/javascript">
        Shadowbox.init( 
        {
           /* Add call to hook into the event */
           onFinish : function () 
           { 
                /* Make the image viewport draggable */
                $( "img#sb-player" ).draggable({ axis: "x" });
           }, 
           onOpen: function() 
           { 
           }, 
           players: ['html','img', 'iframe' ,'inline']   } );
</script>

But the user is not able to swipe through the galery, because there is no function call to go to the next or previous image. So we have to add them. That requires a variable at the beginning of the code to save the current position of the image without dragging. Then we have to add an event when the user stops dragging the image to get the image position after dragging to calculate the distance between start and end position. We can use the calculated value to get the direction (left or right) of the swipe gesture.

   <script type="text/javascript">
            Shadowbox.init( 
            {
               /* Add call to hook into the event */
               onFinish : function () 
               { 
                    /* Make the image viewport draggable */
                    $( "img#sb-player" ).draggable({ axis: "x" });

                    /* Save the current position of the image in a global variable */
                    leftrightDirection = $( "img#sb-player" ).offset().left;  

                    /** Execute the calculation of the direction and call the next/prev functions **/
                    $( "img#sb-player" ).draggable({ stop: function( event, ui ) 
                    {  

                        var leftrightDirectionCalculated = leftrightDirection - $( "img#sb-player" ).offset().left;

                        if (   Math.abs( leftrightDirectionCalculated ) > 30  )
                        {

                            if ( leftrightDirectionCalculated < 0 )
                            {
                                /* Go to the previous image */
                                Shadowbox.previous()
                            }
                            else
                            {
                                /* Go to the next image */
                                Shadowbox.next();
                            }

                        }

                     }});


               }, 
               onOpen: function() 
               { 
               }, 
               players: ['html','img', 'iframe' ,'inline']   } );
    </script>

We're almost done. This works so far, but the problem are Shadowbox galeries with only one single image. In this case the image must not be draggable.

Another problem is the first and the last image of the galery. For example if the first image is visible, it's possible to drag to the right - even if there is no previous image (because it's the first one!). That's the reason, we have to check if the current image is the first or the last one and deny a drag of the image to the left or right.

On every called drag event (for every pixel the image moves) we have to calculate the distance and check, if it's allowed to move the image. If not, we just set the start position. So the first image for example can only be moved in one direction.

            if (  Shadowbox.hasNext() == false )
            {
                if(ui.position.left < startPosition)
                {
                    ui.position.left = startPosition;
                }
                else if(ui.position.left > 250)
                {
                    ui.position.left = 250;
                }
                    startPosition = ui.position.left;
            }

            if (  Shadowbox.current == 0 )
            {
                if(ui.position.left > startPosition)
                {
                    ui.position.left = startPosition;
                }
                else if(ui.position.left < -250)
                {
                    ui.position.left = -250;
                }
                    startPosition = ui.position.left;
            }

Now we're done. It's actualy very easy to modify current Shadowbox installations. The code is not the best, but maybe it's a good basis for further improvements (for example a gesture for closing the enlarged viewer).

Complete script:

Shadowbox.init( { onFinish : function () {

    if ( Shadowbox.hasNext() == false &&  Shadowbox.current == 0 )
    {
        // If there is only one image at the galery - just do nothing!
    }
    else
    {

       /* Save the current image position */
       leftrightDirection = $( "img#sb-player" ).offset().left;  

       /* Make the image draggable, but only in x-direction */
       $( "img#sb-player" ).draggable({ axis: "x" });


       /* After dragging go to previous / next image in the galery */
       $( "img#sb-player" ).draggable({ stop: function( event, ui ) 
        {  

            var leftrightDirectionCalculated = leftrightDirection - $( "img#sb-player" ).offset().left;

            if (   Math.abs( leftrightDirectionCalculated ) > 30  )
            {

                if ( leftrightDirectionCalculated < 0 )
                {
                    Shadowbox.previous()
                }
                else
                {
                    Shadowbox.next();
                }

            }

         }});

        $( "img#sb-player" ).draggable({ start: function( event, ui ) 
        {  
            startPosition = ui.position.left;

         }});


      /* Improve behaviour for the first or last image */
      $( "img#sb-player" ).draggable({ drag: function( event, ui ) 
        {  



            if (  Shadowbox.hasNext() == false )
            {
                if(ui.position.left < startPosition)
                {
                    ui.position.left = startPosition;
                }
                else if(ui.position.left > 250)
                {
                    ui.position.left = 250;
                }
                    startPosition = ui.position.left;
            }

            if (  Shadowbox.current == 0 )
            {
                if(ui.position.left > startPosition)
                {
                    ui.position.left = startPosition;
                }
                else if(ui.position.left < -250)
                {
                    ui.position.left = -250;
                }
                    startPosition = ui.position.left;
            }

         }});    

         } // Ende Fallunterscheidung zwischen Galerie und 1-Bild-Lightbox







                                }, onOpen: function() { }, players: ['html','img', 'iframe' ,'inline']  , resizeDuration: 0 } );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM