用jQuery滑动菜单

时间:2019-12-03 20:15:51

标签: javascript jquery html css

我想使用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>

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

1 个答案:

答案 0 :(得分:2)

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

第二,在打开新菜单之前,您需要关闭现有菜单(如果已打开)。这是您想要的状态。

我在下面创建了一些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>