使用 jquery 滑动菜单

Posted

技术标签:

【中文标题】使用 jquery 滑动菜单【英文标题】:swipe menu with jquery 【发布时间】:2020-03-28 14:04:36 【问题描述】:

我想在 jquery mobile 的右侧和左侧有一个菜单。 在这个 (tutorial) 的帮助下,我尝试在左侧制作一个菜单,在右侧制作另一个菜单

我来到了这个结果

$(document).ready(function() 
  // only small screens
  if ($(window).width() <= 1600) 
    // show menu on swipe to right
    $(document).on('swiperight', function(e) 
      e.preventDefault();
      $('#menu').animate(
        left: '0'
      );
    );  // hide menu on swipe to left
    $(document).on('swipeleft', function(e) 
      e.preventDefault();
      $('#menu').animate(
        left: '-100%'
      );
    );
    // show menu on swipe to left
    $(document).on('swipeleft', function(e) 
      e.preventDefault();
      $('#menu2').animate(
        right: '0'
      );
    );  // hide menu on swipe to right
    $(document).on('swiperight', function(e) 
      e.preventDefault();
      $('#menu2').animate(
        right: '-100%'
      );
    );
  
);
* 
  margin: 0;
  padding: 0;
  outline: none;
  font-family: sans-serif;


#menu 
  background-color: #E64A4A;
  width: 80%;
  height: 400px;
  position: fixed;
  top: 0;
  left: -100%;
  color: #fff;


#menu2 
  background-color: #000;
  width: 80%;
  height: 400px;
  position: fixed;
  top: 0;
  right: -100%;
  color: #fff;


h1 
  text-align: center;
  margin: 20px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mobile/1.4.5/jquery.mobile.min.js"></script>
<ul id="menu">
  <!--   YOUR LINKS GOES HERE   -->
</ul>
<ul id="menu2">
  <!--   YOUR LINKS GOES HERE   -->
</ul>
<h1>Swipe to &lt;&lt; or &gt;&gt;</h1>

问题是没有菜单就没有中间点 为什么没有菜单就没有中间地带?我哪里出错了?

【问题讨论】:

查看 JQM 文档:The demo page has two menus, one at each side. Both can be opened with swipe 【参考方案1】:

首先通过滑动而不是菜单来分离你的逻辑。

其次,您需要先关闭现有菜单(如果已打开),然后再打开新菜单。这是你想要的状态。

我在下面创建了一些 jQuery 插件来简化逻辑并提高可读性。

更新:我通过存储一个属性来确定菜单在屏幕的哪一侧,从而简化并验证了逻辑。

(function() 
  $.swipeMenu = function(selector, options) 
    let $self = $(selector);
    $self.attr('data-direction', options.direction); // attribute
    $self.menuDirection = options.direction; // in-memory jQuery property
    return $self;
  ;
  $.fn.openMenu = function() 
    this.animate( [this.menuDirection] : 0 );
  ;
  $.fn.closeMenu = function() 
    this.animate( [this.menuDirection] : '-100%' );
  ;
  $.fn.isMenuOpened = function() 
    return parseInt(this.css(this.menuDirection), 10) === 0;
  ;
)(jQuery);

$(document).ready(function() 
  const $leftMenu  = $.swipeMenu('#menu-1',  direction : 'left' );
  const $rightMenu = $.swipeMenu('#menu-2',  direction : 'right' );
  if ($(window).width() <= 1600) 
    $(document).on('swipeleft', function(e) 
      e.preventDefault();
      if ($leftMenu.isMenuOpened()) 
        $leftMenu.closeMenu();
       else 
        $rightMenu.openMenu();
      
    );
    $(document).on('swiperight', function(e) 
      e.preventDefault();
      if ($rightMenu.isMenuOpened()) 
        $rightMenu.closeMenu();
       else 
        $leftMenu.openMenu();
      
    );
  
);
* 
  margin: 0;
  padding: 0;
  outline: none;
  font-family: sans-serif;


#menu-1 
  background-color: #E64A4A;
  width: 80%;
  height: 400px;
  position: fixed;
  top: 0;
  left: -100%;
  color: #fff;


#menu-2 
  background-color: #000;
  width: 80%;
  height: 400px;
  position: fixed;
  top: 0;
  right: -100%;
  color: #fff;


h1 
  text-align: center;
  margin: 20px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mobile/1.4.5/jquery.mobile.min.js"></script>
<ul id="menu-1">
  <!--   YOUR LINKS GOES HERE   -->
  <li><a href="#">Foo</a></li>
  <li><a href="#">Bar</a></li>
</ul>
<ul id="menu-2">
  <!--   YOUR LINKS GOES HERE   -->
  <li><a href="#">Bam</a></li>
  <li><a href="#">Pow</a></li>
  <li><a href="#">Zip</a></li>
</ul>
<h1>Swipe to &lt;&lt; or &gt;&gt;</h1>

改进的 jQuery 插件

下一步是添加将菜单相互链接的功能,并在插件中添加事件侦听器。

/**
 * @plugin: jquery.swipe-menu.js
 */
(function($, window, undefined) 
  const defaults =  direction: 'left' ;
  const methods = 
    init: function(options) 
      options = $.extend(, defaults, options);
      return this
        .addClass('swipe-menu')
        .attr('data-direction', options.direction)
        .data('direction', options.direction)
        .css(
          [options.direction] : '-100%',
          // The default styles below could be defined in a stylesheet
          // e.g. jquery.swipe-menu.css
          position : 'fixed',
          top : 0,
          width : '80%',
          height : '100vh'
        );
    ,
    open: function() 
      return this.animate( [this.data('direction')]: 0 );
    ,
    close: function() 
      return this.animate( [this.data('direction')]: '-100%' );
    ,
    isOpen: function() 
      return parseInt(this.css(this.data('direction')), 10) === 0;
    
  ;
  $.fn.swipeMenu = function(methodOrOptions) 
    if (methods[methodOrOptions]) 
      return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
     else if (typeof methodOrOptions === 'object' || !methodOrOptions) 
      return methods.init.apply(this, arguments);
     else 
      $.error('Method ' + methodOrOptions + ' does not exist on jQuery.swipe-menu');
    
  ;
)(jQuery);

$(document).ready(function() 
  const $leftMenu = $('#menu-1').swipeMenu();
  const $rightMenu = $('#menu-2').swipeMenu( direction: 'right' );
  if ($(window).width() <= 1600) 
    $(document).on('swipeleft', function(e) 
      e.preventDefault();
      if ($leftMenu.swipeMenu('isOpen')) 
        $leftMenu.swipeMenu('close');
       else 
        $rightMenu.swipeMenu('open');
      
    );
    $(document).on('swiperight', function(e) 
      e.preventDefault();
      if ($rightMenu.swipeMenu('isOpen')) 
        $rightMenu.swipeMenu('close');
       else 
        $leftMenu.swipeMenu('open');
      
    );
  
);
h1 
  text-align: center;
  line-height: 100vh;
  margin: 0;


#menu-1 
  background-color: #E64A4A;
  color: #fff;


#menu-2 
  background-color: #4AE64A;
  color: #fff;


.unselectable 
  user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -o-user-select: none;

.ui-mobile-viewport, .ui-page  margin: 0; padding: 0; 
.ui-loader  display: none; 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mobile/1.4.5/jquery.mobile.min.js"></script>
<h1 class="unselectable">Swipe to &lt;&lt; or &gt;&gt;</h1>
<div id="menu-1">
  <ul>
    <!--   YOUR LINKS GOES HERE   -->
    <li><a href="#">Foo</a></li>
    <li><a href="#">Bar</a></li>
  </ul>
</div>
<div id="menu-2">
  <ul>
    <!--   YOUR LINKS GOES HERE   -->
    <li><a href="#">Bam</a></li>
    <li><a href="#">Pow</a></li>
    <li><a href="#">Zip</a></li>
  </ul>
</div>

几乎完整的 jQuery 插件

菜单现在相互链接,事件处理程序位于插件内部。所以页面现在唯一负责的逻辑就是通过初始化和链接来建立菜单。

$(document).ready(function() 
  $('#menu-1').swipeMenu( link : '#menu-2' );
  $('#menu-2').swipeMenu( direction: 'right', link : '#menu-1' );
);

/**
 * @plugin: jquery.swipe-menu.js
 */
(function($, window, undefined) 
  const defaults =  direction: 'left', link : null ;
  const methods = 
    init: function(options) 
      options = $.extend(, defaults, options);
      attachSwipeEventHandlers(this);
      return this
        .addClass('swipe-menu')
        .attr('data-direction', options.direction)
        .data('direction', options.direction)
        .data('link', options.link)
        .css(
          [options.direction] : '-100%',
        )
    ,
    open: function() 
      return this.animate( [this.data('direction')]: 0 );
    ,
    close: function() 
      return this.animate( [this.data('direction')]: '-100%' );
    ,
    isOpen: function() 
      return parseInt(this.css(this.data('direction')), 10) === 0;
    ,
    link: function(link) 
      return this.data('link', link);
    ,
    unlink: function() 
      return this.removeData('link');
    ,
    linkedMenu : function() 
      return this.data('link') ? $(this.data('link')) : null;
    ,
  ;
  $.fn.swipeMenu = function(methodOrOptions) 
    if (methods[methodOrOptions]) 
      return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
     else if (typeof methodOrOptions === 'object' || !methodOrOptions) 
      return methods.init.apply(this, arguments);
     else 
      $.error('Method ' + methodOrOptions + ' does not exist on jQuery.swipe-menu');
    
  ;
  function handleOpen($menu, $linkedMenu) 
    if (!$menu.swipeMenu('isOpen')) 
      if ($linkedMenu == null || !$linkedMenu.swipeMenu('isOpen')) 
        $menu.swipeMenu('open');
      
    
  
  function handleClose($menu, $linkedMenu) 
    if ($menu.swipeMenu('isOpen')) 
      $menu.swipeMenu('close');
    
  
  function handleSwipe($menu, action) 
    let $linkedMenu = $menu.swipeMenu('linkedMenu');
    let menuDirection = $menu.data('direction');
    let linkedMenuDirection = $linkedMenu ? $linkedMenu.data('direction') : null;
    let reverse = menuDirection !== defaults.direction;
    switch (action) 
      case 'left' :
        reverse ? handleOpen($menu, $linkedMenu) : handleClose($menu, $linkedMenu);
        break;
      case 'right' :
        reverse ? handleClose($menu, $linkedMenu) : handleOpen($menu, $linkedMenu);
        break;
    
  
  function attachSwipeEventHandlers($menu) 
    $(document).on(
      'swipeleft' : function(e) 
        e.preventDefault();
        handleSwipe($menu, 'left');
      ,
      'swiperight' : function(e) 
        e.preventDefault();
        handleSwipe($menu, 'right');
      
    );
  
)(jQuery);

$(document).ready(function() 
  $('#menu-1').swipeMenu( link : '#menu-2' );
  $('#menu-2').swipeMenu( direction: 'right', link : '#menu-1' );
);
/* jquery.swipe-menu.js */
.swipe-menu 
  position : fixed;
  top : 0;
  width : 80%;
  height : 100vh;


/* Other styles... */
h1 
  text-align: center;
  line-height: 100vh;
  margin: 0;


#menu-1  background: #E64A4A; color: #fff; 
#menu-2  background: #4AE64A; color: #fff; 

.unselectable 
  user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -o-user-select: none;

.ui-mobile-viewport, .ui-page  margin: 0; padding: 0; 
.ui-loader  display: none; 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mobile/1.4.5/jquery.mobile.min.js"></script>
<h1 class="unselectable">Swipe to &lt;&lt; or &gt;&gt;</h1>
<div id="menu-1">
  <ul>
    <!--   YOUR LINKS GOES HERE   -->
    <li><a href="#">Foo</a></li>
    <li><a href="#">Bar</a></li>
  </ul>
</div>
<div id="menu-2">
  <ul>
    <!--   YOUR LINKS GOES HERE   -->
    <li><a href="#">Bam</a></li>
    <li><a href="#">Pow</a></li>
    <li><a href="#">Zip</a></li>
  </ul>
</div>

【讨论】:

我在浏览菜单时出现问题,但没有滑动。当我按 f5 时,问题就消失了ibb.co/vQBH5vt @Valy 在我的最后一个示例中,我将列表包装在 div 中,并将 id 从列表移动到包装 div。请重新评估上面的完整示例。

以上是关于使用 jquery 滑动菜单的主要内容,如果未能解决你的问题,请参考以下文章

下拉菜单:使用 jQuery 悬停时无限滑动

如何在 jquery 3.1.0 中使用“滑动菜单 Jquery Mobile”?

从页面顶部滑动导航菜单 - Jquery

jQuery:菜单在内容顶部向下滑动,而不是向下推送内容

jquery制作移动端菜单栏左右滑动

jQuery水平滑动菜单