我有一个下拉菜单,子菜单放在不同的元素上。所以基本上当鼠标离开菜单项时,子菜单立即关闭,因为子菜单不是子菜单。
var menuItem = $(".menu-item");
menuItem.hover(hoverIn, hoverOut);
function hoverIn() {
var mnItemMeta = $(this)[0].getBoundingClientRect();
$(".sub-menu").css({
opacity: 1,
left: mnItemMeta.left
})
}
function hoverOut() {
$(".sub-menu").css({
opacity: 0
})
}
html,body{background-color: #efefef;}
.menu {
list-style: none;
padding-left: 0;
display: flex;
justify-content: center;
}
a {
display: block;
padding: 10px 20px;
text-decoration: none;
color: inherit;
}
.sub-menu {
opacity: 0;
background-color: white;
position: absolute;
transition: .2s ease;
}
.sub-menu-list {
list-style: none;
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li class="menu-item"><a href="#">Menu Item</a>
</li>
</ul>
<div class="sub-menu">
<ul class="sub-menu-list">
<li><a href="#">Sub Menu 1</a>
</li>
<li><a href="#">Sub Menu 2</a>
</li>
<li><a href="#">Sub Menu 3</a>
</li>
<li><a href="#">Sub Menu 4</a>
</li>
</ul>
</div>
起源
答案:
你可以放置 sub-menu
在里面 menu-item
。
var menuItem = $(".menu-item");
menuItem.hover(hoverIn, hoverOut);
function hoverIn() {
var mnItemMeta = $(this)[0].getBoundingClientRect();
$(".sub-menu").css({
opacity: 1,
left: mnItemMeta.left
})
}
function hoverOut() {
$(".sub-menu").css({
opacity: 0
})
}
html, body {
background-color: #efefef;
}
.menu {
list-style: none;
padding-left: 0;
display: flex;
justify-content: center;
}
a {
display: block;
padding: 10px 20px;
text-decoration: none;
color: inherit;
}
.sub-menu {
opacity: 0;
background-color: white;
position: absolute;
transition: .2s ease;
}
.sub-menu-list {
list-style: none;
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li class="menu-item"><a href="#">Menu Item</a>
<div class="sub-menu">
<ul class="sub-menu-list">
<li><a href="#">Sub Menu 1</a></li>
<li><a href="#">Sub Menu 2</a></li>
<li><a href="#">Sub Menu 3</a></li>
<li><a href="#">Sub Menu 4</a></li>
</ul>
</div>
</li>
</ul>
另一种方法是检查 hover
的状态 .menu-item
和 .sub-menu
。你需要在这里使用一点暂停,以防止它提前关闭。
var timeout,
hovered = false,
menuItem = $(".menu-item, .sub-menu").hover(hoverIn, hoverOut);;
function hoverIn() {
hovered = true;
var mnItemMeta = this.getBoundingClientRect();
$(".sub-menu").show().css({
opacity: 1,
left: mnItemMeta.left,
});
}
function hoverOut() {
hovered = false;
clearTimeout(timeout);
timeout = setTimeout(function() {
if (!hovered) {
$(".sub-menu").css({
opacity: 0,
}).hide()
}
}, 100);
}
html, body {
background-color: #efefef;
}
.menu {
list-style: none;
padding-left: 0;
display: flex;
justify-content: center;
}
a {
display: block;
padding: 10px 20px;
text-decoration: none;
color: inherit;
}
.sub-menu {
opacity: 0;
background-color: white;
position: absolute;
transition: .2s ease;
}
.sub-menu-list {
list-style: none;
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li class="menu-item"><a href="#">Menu Item</a></li>
</ul>
<div class="sub-menu">
<ul class="sub-menu-list">
<li><a href="#">Sub Menu 1</a></li>
<li><a href="#">Sub Menu 2</a></li>
<li><a href="#">Sub Menu 3</a></li>
<li><a href="#">Sub Menu 4</a></li>
</ul>
</div>
你可以添加
.sub-menu::before{
content:'';
height: <height of menu item>
width: 100%;
position:absolute;
bottom:100%;
}
放置 hoverOut
在...上 .sub-menu
。
我今天在你的剧本上玩了一段时间,从你的开始 小提琴,而不是部分片段......
你太近了......
但问题是你有两个不同的父元素类来处理(读取:事件处理程序绑定到它们)...并以不同的方式处理。
当您将鼠标从打开子菜单的元素移动到另一个应该保持打开状态的元素时,不应触发某些事件。一个 mouseout
只有当鼠标不输入另一个时才会发生事件 menu___item
或者a dropdown-menu__content
“快速的”。
mouseenter
和 mouseout
很好 快速 在触发器上...比人类鼠标移动更快。
这里有一个小的100ms延迟。
一个 setTimeout()
设置 dropdown-holder
至 display:none
留下这些元素和一个 clearTimeout
在进入。
$(".menu__item").hover(
function() {
$(".dropdown-holder").css({"display":"block"});
displaySubMenu( $(this) );
clearTimeout(NavDelay);
},
function(){
setNavDelay();
});
$(".dropdown-menu__content").hover(
function() {
clearTimeout(NavDelay);
},
function(){
setNavDelay();
});
setTimout函数很简单:
function setNavDelay(){
NavDelay = setTimeout(function(){
$(".dropdown-holder").css({"display":"none"});
},100);
}
这是子菜单显示功能,没有那么多修改:
function displaySubMenu(element){
var itemMeta = element[0].getBoundingClientRect();
//console.log( itemMeta );
var subID = element.data('sub');
console.log(subID);
var subCnt = $(subID).find(".dropdown-menu__content").css({"display":"block"});
var subMeta = subCnt[0].getBoundingClientRect();
//console.log( subMeta );
var subCntBtm = subCnt.find(".bottom-section");
menuHoveredID = subID; // Let's Keep this info in memory in a var that has global scope
$(drBg).css({
"display":"block",
"left": itemMeta.left - ((subMeta.width / 2) - itemMeta.width / 2),
"width": subMeta.width,
"height": subMeta.height
});
$(drBgBtm).css({
"top": subCntBtm.position().top
});
$(drArr).css({
"display":"block",
"left": itemMeta.left + itemMeta.width / 2 - 10
});
$(drCnt).css({
"display":"block",
"left": itemMeta.left - ((subMeta.width / 2) - itemMeta.width / 2),
"width": subMeta.width,
"height": subMeta.height
});
// Ensure the right content is displayed
$(".dropdown-menu__content").css({
"display":"none"
});
$(menuHoveredID).find(".dropdown-menu__content").css({
"display":"block"
});
}
为了确保显示正确的内容, menuHoveredID
变量通过函数传递给函数 mouseenter
处理程序 menu__item
hover
。
你的onload声明:
var dr = $(".dropdown__content"),
drBg = $(".dropdown__bg"),
drBgBtm = $(".dropdown__bg-bottom"),
drArr = $(".dropdown__arrow"),
drMenu = $(".dropdown-menu__content"),
drCnt = $(".dropdown__content"),
menuHoveredID ="",
NavDelay;
我剥夺了这种情感并增加了两个变量......
如果你注意到,我也纠正了分号/昏迷......;)
如果您将第一个js行更改为: var menuItem = $(".menu-item, .sub-menu");
然后添加 top: 3em;
到了 .menu-list
css(提供与...的微小重叠) .menu
div并删除闪烁)然后一切都应该是好的。
var menuItem = $(".menu-item, .sub-menu");
menuItem.hover(hoverIn, hoverOut);
function hoverIn() {
var mnItemMeta = $(this)[0].getBoundingClientRect();
$(".sub-menu").css({
opacity: 1,
left: mnItemMeta.left
})
}
function hoverOut() {
$(".sub-menu").css({
opacity: 0
})
}
html,body{background-color: #efefef;}
.menu {
list-style: none;
padding-left: 0;
display: flex;
justify-content: center;
}
a {
display: block;
padding: 10px 20px;
text-decoration: none;
color: inherit;
}
.sub-menu {
opacity: 0;
background-color: white;
position: absolute;
transition: .2s ease;
top: 3em;
}
.sub-menu-list {
list-style: none;
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li class="menu-item"><a href="#">Menu Item</a>
</li>
</ul>
<div class="sub-menu">
<ul class="sub-menu-list">
<li><a href="#">Sub Menu 1</a>
</li>
<li><a href="#">Sub Menu 2</a>
</li>
<li><a href="#">Sub Menu 3</a>
</li>
<li><a href="#">Sub Menu 4</a>
</li>
</ul>
</div>
这是一个例子
- 将伪元素添加到子菜单以提供悬停的重叠区域。它仅为演示用途的黄色。
- 菜单和子菜单中的鼠标悬停仅设置变量。子菜单隐藏在一个单独的函数中,它评估变量。需要稍微超时才能允许从一个更改为另一个。
var menuItem = $(".menu-item");
var submenuItem = $(".sub-menu");
var hoverMenu = false;
var hoverSubmenu = false;
menuItem.hover(hoverIn, hoverOut);
function hoverIn() {
hoverMenu = true;
var mnItemMeta = $(this)[0].getBoundingClientRect();
$(".sub-menu").css({
opacity: 1,
left: mnItemMeta.left
})
}
function hoverOut() {
hoverMenu = false;
setTimeout (hide, 10);
}
submenuItem.hover(hoverSmIn, hoverSmOut);
function hoverSmIn() {
hoverSubmenu = true;
}
function hoverSmOut() {
hoverSubmenu = false;
setTimeout (hide, 10);
}
function hide() {
if (hoverMenu == false && hoverSubmenu == false) {
$(".sub-menu").css({
opacity: 0
})
}
}
html,body{background-color: #efefef;}
.menu {
list-style: none;
padding-left: 0;
display: flex;
justify-content: center;
}
a {
display: block;
padding: 10px 20px;
text-decoration: none;
color: inherit;
}
.sub-menu {
opacity: 0;
background-color: white;
position: absolute;
transition: .2s ease;
}
.sub-menu:before {
content: "";
position: absolute;
width: 100%;
left: 0px;
bottom: 100%;
height: 26px;
background-color: yellow;
}
.sub-menu-list {
list-style: none;
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li class="menu-item"><a href="#">Menu Item</a>
</li>
</ul>
<div class="sub-menu">
<ul class="sub-menu-list">
<li><a href="#">Sub Menu 1</a>
</li>
<li><a href="#">Sub Menu 2</a>
</li>
<li><a href="#">Sub Menu 3</a>
</li>
<li><a href="#">Sub Menu 4</a>
</li>
</ul>
</div>
好的,我已经找到了解决方案。感谢各位提供一些建议,但我不能接受你们的答案,因为解决方案需要更多的解决方法。
所以,基本上我创建了两个函数,即 startCloseTimeout()
和 stopCloseTimout()
,并将它绑定在两者上 menu-item
和 submenu
。
这是函数本身:
var startCloseTimeout = function (){
closeDropdownTimeout = setTimeout( () => closeDropdown() , 50 );
},
stopCloseTimeout = function () {
clearTimeout( closeDropdownTimeout );
};
以下是我如何绑定鼠标事件:
//- Binding mouse event to each menu items
menuItems.forEach( el => {
//- mouse enter event
el.addEventListener( 'mouseenter', function() {
stopCloseTimeout();
openDropdown( this );
}, false );
//- mouse leave event
el.addEventListener( 'mouseleave', () => startCloseTimeout(), false);
} );
//- Binding mouse event to each sub menus
menuSubs.forEach( el => {
el.addEventListener( 'mouseenter', () => stopCloseTimeout(), false );
el.addEventListener( 'mouseleave', () => startCloseTimeout(), false );
} );
那么,这段代码如何工作?
通过创建关闭超时处理程序,我们可以控制下拉列表何时关闭。
当鼠标进入菜单项时,会发生以下情况:
1.停止当前运行 closeDropdownTimout
2.打开相关的下拉菜单
当鼠标离开菜单项时,它会启动 closeDropdownTimout
。
但是下拉菜单仍然如何打开?由于我们在下拉菜单中设置了相同的操作,因此 closeDropdownTimout
好清除并取消关闭行动。
有关完整源代码,您可以在codepen上查看 http://codepen.io/ariona/pen/pENkXW
谢谢。