不稳定的mouseenter/mouseleave子菜单 [英] Unstable mouseenter/mouseleave submenu

查看:81
本文介绍了不稳定的mouseenter/mouseleave子菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个通过将鼠标悬停在主菜单上而激活的子菜单.

I'm building a submenu activated by hovering over the main menu.

它可以正常工作,我正在尝试使它在清理我的代码之前顺利运行.

It's working and I'm trying to make is work smoothly before cleaning up my code.

问题是,不管它是否起作用,都是随机的.加载页面并将鼠标导航到悬停区域可以正常工作.但是,然后将其稍微滑动一下,然后来回快速移动就会破坏它.

Problem is that it's kind of random if it's working or not. Loading the page and navigating the mouse to the hover-area works fine. But then swiping it around a bit and going back and forth fast breaks it.

所以,我猜测它与超时有某种关系,但不确定为什么-可能有更好的方法来实现它吗?

So, I'm guessing it has something to do with the timeout somehow, but not sure why - might there be a better way of achieving it?

HTML主菜单以及子菜单和JS/Jquery的占位符如下

// Example of menu items
var menuItems1 = [
  '<li><a href="#">Undermeny1 1</a></li>',
  '<li><a href="#">Undermeny1 2</a></li>',
  '<li><a href="#">Undermeny1 3</a></li>',
  '<li><a href="#">Undermeny1 4</a></li>'
];

var inSubMenu = false;
var lastId = "";
$(document).on('mouseenter', '.subMenuHoverArea', function() {

  if ($(this).hasClass('subMenuJS')) {
    var thisid = $(this).attr('id');
  } else {
    thisid = lastId;
  }

  if (thisid != lastId && lastId != "") {
    $('#subMenuContent').empty();
    populateMenu(thisid);
  } else {

    if (!inSubMenu) {
      $('#subMenuContent').empty();
      populateMenu(thisid);
      $('.subMenuSubMenu').fadeIn('fast');
    }

  }
  lastId = thisid;
  inSubMenu = true;

});
$(document).on('mouseleave', '.subMenuHoverArea', function() {
  setTimeout(function() {
    if (!inSubMenu) {
      $('#subMenuContent').empty();
      $('.subMenuSubMenu').fadeOut('fast');
    }
    inSubMenu = false;

  }, 350);

});

function populateMenu(menuId) {
  // Populates ul element with li from chosen array by appending it through a for loop. Not related to problem
for(var i = 0;  i < menuItems1.length; i++){
					$('#subMenuContent').append(menuItems1[i]);
				}
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
  <li><a id="menu1" href="#" class="subMenuHoverArea subMenuJS">Menu 1</a></li>
  <li><a id="menu2" href="#" class="subMenuHoverArea subMenuJS">Menu 2</a></li>
  <li><a id="menu3" href="#" class="subMenuHoverArea subMenuJS">Menu 3</a></li>
</ul>
<div class="subMenuSubMenu">
  <div class="contentMain">
    <ul id="subMenuContent" class="subMenuHoverArea"></ul>
  </div>
</div>

推荐答案

这是我曾经写过的悬停菜单.这样做的好处是,它会延迟鼠标悬停工作.因此,如果您真正快速地移动多个菜单项,则不会获得闪烁效果".您必须将鼠标悬停在元素上150ms才能起作用.您可以根据自己的喜好调整该值.

This is a hover menu I ever wrote. The advantage of this is that it uses a delay for the hover to work. So if you move really quick over multiple menu items you wont get a "flashing effect". You have to hover over an element for 150ms for it to work. You can adjust this value to your liking.

虽然看起来您的衰落功能似乎会引起一些麻烦.因此,我在css中创建了相同的效果,并使用类进行切换,从而使其工作更加顺畅.

It looked like your fading functions seem to cause some trouble though. Therefore i created the same effect in css and used classes to toggle which made it work a lot smoother.

这是如何工作的:

  • 在mouseenter和mouseleave事件上,当前时间都保存在全局变量lastAction中.
  • 在mouseenter和mouseleave事件上,计时器都会启动. hoverdelay毫秒后,计时器结束.
  • 当计时器结束时,它将检查之前保存的时间是否仍然与全局变量中的时间相同.如果在此期间发生了另一个mouseenter/mouseleave事件,则全局值将具有不同的值.如果是这种情况,则什么也不做,否则运行属于该事件的代码.
  • On both mouseenter and mouseleave events the current time is saved in a global variable lastAction.
  • On both mouseenter and mouseleave events a timer will start. After hoverdelay in milliseconds the timer ends.
  • When the timer end it will check if the time saved before is still the same as in the global variable. If an other mouseenter/mouseleave event has occurred during this time the global will have a different value. If that is the case do nothing, otherwise run the code belonging to the event.

我用css效果替换了jQuery淡入淡出功能.其原因是因为fadeIn()fadeOut()之间的快速变化,淡入淡出效果不好. AddClass()removeClass()的效果更好.通过在不透明度上添加过渡效果,您可以获得相同的fadeIn/fadeOut效果. 如果您希望定时更快或更慢,只需更改秒数即可.

I replaced the jQuery fade functions with a css effect. The reason for this is because the fade effect is not good for fast changes between fadeIn() and fadeOut(). AddClass() and removeClass() works a lot better for this. By adding a transition effect on the opacity you get the same fadeIn/fadeOut effect. If you want timing to be faster or slower just change the amount of seconds.

var hoverdelay = 150;
var lastAction = 0;

$(document).ready(function() {
  $('#wrapper').on({
    mouseenter: mouseEnterFunction,
    mouseleave: mouseLeaveFunction
  }, '.subMenuHoverArea');
});

function mouseEnterFunction() {
  var now = (new Date().getTime());
  var id = $(this).attr('id');
  lastAction = now;
  window.setTimeout(function() {
    if (lastAction === now) {
      showMenu(id);
    }
  }, hoverdelay);
}

function mouseLeaveFunction() {
  var now = (new Date().getTime());
  lastAction = now;
  window.setTimeout(function() {
    if (lastAction === now) {
      hideMenu();
    }
  }, hoverdelay);
}

function showMenu(id) {
  $('#subMenuContent').empty().append('<li>'+ id + '</li>').addClass('activeMenu');
}

function hideMenu() {
  $('#subMenuContent').removeClass('activeMenu');
}

.subMenuJS {
  background-color: yellow;
}

#subMenuContent {
  background-color: pink;
}

.menu {
  opacity: 0;
  transition: opacity 0.5s;
}

.activeMenu {
  opacity: 1;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='wrapper'>
  <ul>
    <li><a id="menu1" href="#" class="subMenuHoverArea subMenuJS">Menu 1</a></li>
    <li><a id="menu2" href="#" class="subMenuHoverArea subMenuJS">Menu 2</a></li>
    <li><a id="menu3" href="#" class="subMenuHoverArea subMenuJS">Menu 3</a></li>
  </ul>
  <div class="subMenuSubMenu">
    <div class="contentMain">
      <ul id="subMenuContent" class="subMenuHoverArea menu">test</ul>
    </div>
  </div>
</div>

回答您有关每次创建日期对象的效率如何的问题.这是一段执行10000次的代码.

To answer your question about how efficient it is to create a date object every time. Here is a piece of code that does it 10000 times.

对我来说,经常这样做需要10到20毫秒.我认为,在更糟的情况下,如果用户真的很痉挛,则该事件最多每秒发生100次.因此,我认为性能不是问题.在我的网站上也从未抱怨过它.

For me it will cost 10 till 20 ms to do it that often. I think that in worse case scenario that event happens 100 times in a second at max if the user is really spastic. Therefore I don't think performance is an issue. Never had complains about it on my site too.

var start = (new Date().getTime());

for(var i = 0; i < 10000; i++) {
  var dummy = (new Date().getTime());
}

var end = (new Date().getTime());

console.log((end - start) + ' ms');

这篇关于不稳定的mouseenter/mouseleave子菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆