为移动触摸设备添加图像滑动支持到Shadowbox.js

时间:2015-02-17 19:43:18

标签: javascript jquery mobile lightbox shadowbox

我在各种网站上使用Shadowbox.js(基于网络的查看器,如lightbox),到目前为止效果很好。唯一的问题是对移动设备的不良支持。

无法通过滑动当前图像来更改galery中的图像,因此用户必须使用viewer-viewport底部的非常小的导航按钮。 (也可以使用键盘导航,但不能在移动设备上使用)

这不仅仅是这些导航按钮的难以使用。导航按钮上的每次点击都会触发一个缩放功能,其中包含聚焦区域的详细视图 - 需要再次点击以确认切换到下一个或上一个图像。

如果有可能使galery像默认的android galery查看器或类似的移动应用程序一样,那将是很棒的。

我正在使用shadowbox的jquery版本。

1 个答案:

答案 0 :(得分:0)

有一个示例脚本如何改进Shadowbox.js:

Image swipe for Shadowbox.js on mobile device

首先,您需要使用Shadowbox.js的jQuery版本。此外,还需要jQuery UIjQuery UI Touch Punch插件(大小:584字节)。没有Punch-plugin,jQuery UI不支持触摸事件。

  1. 添加所需的库(如果尚未完成):
  2.  <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. 现在我们必须查看所需的默认值 - <script> - Shadowbox.js区域:
    2. <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> 

      这是初始化Shadowbox.js查看器的最小javascript调用。 onOpen是其中一个事件,它允许在特定点运行代码。在我们的例子中,需要使用一个事件,在加载放大的图像后触发该事件。我们使用事件onFinish并运行自定义jQuery UI代码,以使查看器的图像视口可拖动到x轴。

      因此用户可以将图像从左向右拖动,反之亦然:

      <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>
      

      但是用户无法在galery中滑动,因为没有函数调用转到下一个或上一个图像。所以我们必须添加它们。这需要代码开头的变量来保存图像的当前位置而不拖动。然后,当用户停止拖动图像以在拖动后获取图像位置以计算开始和结束位置之间的距离时,我们必须添加事件。我们可以使用计算出的值来获取滑动手势的方向(左或右)。

         <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>
      

      我们差不多完成了。到目前为止,这是有效的,但问题是Shadowbox galeries只有一个单一的图像。在这种情况下,图像不得拖动。

      另一个问题是画廊的第一张和最后一张图片。例如,如果第一个图像是可见的,则可以向右拖动 - 即使没有先前的图像(因为它是第一个图像!)。这就是原因,我们必须检查当前图像是第一个还是最后一个图像,并拒绝向左或向右拖动图像。

      在每个被调用的拖动事件中(对于图像移动的每个像素),我们必须计算距离并检查是否允许移动图像。如果没有,我们只设置起始位置。因此,第一个图像只能在一个方向上移动。

                  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;
                  }
      

      现在我们已经完成了。修改当前的Shadowbox安装非常容易。代码不是最好的,但它可能是进一步改进的良好基础(例如关闭放大查看器的手势)。

      完整的脚本:

          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 } );