繁体   English   中英

如何使用 js 和 css 动画关闭下拉菜单?

[英]How to Animate closing dropdown menu with js and css?

我有一个带有子菜单项的菜单,我在打开下拉菜单时设法用 css 关键帧创建了一个简单的动画,但是当下拉菜单关闭时我不能做同样的事情。 关闭下拉菜单时如何添加动画? 如您所见,当您关闭下拉菜单时,没有过渡,它会立即消失。

旧片段

 var dropdownBtn = document.querySelectorAll('.menu-btn'); //Add this for toggling dropdown lastOpened = null; dropdownBtn.forEach(btn => btn.addEventListener('click', function() { var menuContent = this.nextElementSibling; menuContent.classList.toggle("show"); //Add this for toggling dropdown if (lastOpened && lastOpened !== menuContent) lastOpened.classList.remove("show"); lastOpened = menuContent; }));
 .menu-btn { background: #e0e0e0; padding: 10px; margin: 5px 0px 0px 0px; } .menu-btn:hover { background: #000; color: #fff; } .drop_container { display: none; background-color: #017575; animation:animateFromBottom .3s; } .drop_container.show { display: block; } .drop_container > .item { display: flex; flex-direction: column; margin-left: 10px; padding: 10px 0px 0px 0px; } @keyframes animateFromBottom { from{bottom:-50px;opacity:0} to{bottom:0;opacity:1} } @keyframes animateToBottom { from{bottom:0;opacity:1} to{bottom:-50px;opacity:0} }
 <div class="dropdown-menu"> <div class="menu-btn">One</div> <div class="drop_container"> <a class="item" href="#">Contact Us</a> <a class="item" href="#">Visit Us</a> </div> <div class="menu-btn">Two</div> <div class="drop_container"> <a class="item" href="#">Contact Us</a> <a class="item" href="#">Visit Us</a> </div> </div>

编辑片段:我决定不使用 css 关键帧,只使用最大高度进行过渡。 这让我更容易做出改变,我仍然只是一个初学者,只是坚持简单的东西。 但是,当您在项目之间切换时,它仍然没有播放任何动画。 我看到@EmielZuurbier 的解决方案即使在从一个项目切换到另一个项目时也会添加动画,我怎样才能将它添加到我修改后的代码中?

 var dropdownBtn = document.querySelectorAll('.menu-btn'); //Add this for toggling dropdown lastOpened = null; dropdownBtn.forEach(btn => btn.addEventListener('click', function() { var menuContent = this.nextElementSibling; if (!menuContent.classList.contains("show")) { menuContent.classList.add("show"); menuContent.classList.remove("hide"); } else { menuContent.classList.add("hide"); menuContent.classList.remove("show"); } //Add this for toggling dropdown if (lastOpened && lastOpened !== menuContent) lastOpened.classList.remove("show"); lastOpened = menuContent; }));
 .menu-btn { background: #e0e0e0; padding: 10px; margin: 5px 0px 0px 0px; } .menu-btn:hover { background: #000; color: #fff; } .drop_container { overflow: hidden; max-height: 0; } .drop_container.show { max-height: 300px; transition: max-height 0.3s ease-in; } .drop_container.hide { overflow: hidden; max-height: 0; transition: max-height 0.3s ease-out; } .drop_container > .item { display: flex; flex-direction: column; margin-left: 10px; padding: 10px 0px 0px 0px; }
 <div class="dropdown-menu"> <div class="menu-btn">One</div> <div class="drop_container"> <a class="item" href="#">Contact Us</a> <a class="item" href="#">Visit Us</a> </div> <div class="menu-btn">Two</div> <div class="drop_container"> <a class="item" href="#">Contact Us</a> <a class="item" href="#">Visit Us</a> </div> </div>

有多种方法可以实现这一目标。 因为您使用display属性显示和隐藏下拉列表,所以我们需要坚持使用动画。

animateToBottom关键帧创建一个新类。 这个类应该添加一个带有show类的元素应该动画出来之后。

只有在“out”动画完成后才能删除show类。 通过animationend事件,我们可以看到动画何时结束,这样我们就可以隐藏下拉菜单。

 const dropdownBtns = document.querySelectorAll('.menu-btn'); let lastOpened = null; dropdownBtns.forEach(btn => btn.addEventListener('click', function() { const menuContent = this.nextElementSibling; if (lastOpened !== null) { const target = lastOpened; target.addEventListener('animationend', () => { target.classList.remove('show', 'animate-out'); if (target === lastOpened) { lastOpened = null; } }, { once: true }); target.classList.add('animate-out'); } if (lastOpened !== menuContent) { menuContent.classList.add('show'); lastOpened = menuContent; } }));
 .menu-btn { background: #e0e0e0; padding: 10px; margin: 5px 0px 0px 0px; } .menu-btn:hover { background: #000; color: #fff; } .drop_container { display: none; background-color: #017575; animation: animateFromBottom .3s; } .drop_container.show { display: block; } .drop_container.show.animate-out { animation: animateToBottom .3s; } .drop_container>.item { display: flex; flex-direction: column; margin-left: 10px; padding: 10px 0px 0px 0px; } @keyframes animateFromBottom { from { transform: translate3d(0, 10px, 0); opacity: 0 } to { transform: translate3d(0, 0, 0); opacity: 1 } } @keyframes animateToBottom { from { transform: translate3d(0, 0, 0); opacity: 1 } to { transform: translate3d(0, 10px, 0); opacity: 0 } }
 <div class="dropdown-menu"> <div class="menu-btn">One</div> <div class="drop_container"> <a class="item" href="#">Contact Us</a> <a class="item" href="#">Visit Us</a> </div> <div class="menu-btn">Two</div> <div class="drop_container"> <a class="item" href="#">Contact Us</a> <a class="item" href="#">Visit Us</a> </div> </div>

这是一个涉及CSS 过渡CSS 自定义属性的不同解决方案。

使用这种方法,手风琴菜单部分最初设置为.hide

然后在.hide.show之间切换这些部分(使用.classList.toggle() )。

  • 一类.hide表示height0
  • .show类表示heightvar(--openHeight)

height将在这两个值之间进行动画处理。

var(--openHeight)是为每个menuItemData单独计算的 - 它等效于menuItemData.scrollHeight

通过这种技术,我们可以在0和 CSS 无法猜测的值之间实现平滑的 CSS 过渡,但 JavaScript 可以很容易地告诉我们。


工作示例:

 let dropdownMenuItemTitles = document.querySelectorAll('.dropdown-menu-item-title'); dropdownMenuItemTitles.forEach(menuItemTitle => { menuItemTitle.addEventListener('click', (e) => { const menuItemData = e.target.nextElementSibling; menuItemData.style.setProperty('--openHeight', menuItemData.scrollHeight + 'px'); menuItemData.classList.toggle('show'); menuItemData.classList.toggle('hide'); }) });
 .dropdown-menu-item-title { background-color: #a0a0a0; padding: 10px; margin: 5px 0px 0px 0px; cursor: pointer; } .dropdown-menu-item-title:hover { background: #000; color: #fff; } .dropdown-menu-item-data { margin: 0; overflow: hidden; transition: height 0.3s ease-out; } .dropdown-menu-item-data.hide { height: 0; } .dropdown-menu-item-data.show { height: var(--openHeight); } .dropdown-submenu { padding: 0; background-color: #e0e0e0; list-style-type: none; } .dropdown-submenu-item { padding: 12px; }
 <dl class="dropdown-menu"> <div> <dt class="dropdown-menu-item-title">One</dt> <dd class="dropdown-menu-item-data hide"> <ul class="dropdown-submenu"> <li class="dropdown-submenu-item"><a href="#">Contact Us</a></li> <li class="dropdown-submenu-item"><a href="#">Visit Us</a></li> </ul> </dd> </div> <div> <dt class="dropdown-menu-item-title">Two</dt> <dd class="dropdown-menu-item-data hide"> <ul class="dropdown-submenu"> <li class="dropdown-submenu-item"><a href="#">About Us</a></li> <li class="dropdown-submenu-item"><a href="#">Visit Us</a></li> <li class="dropdown-submenu-item"><a href="#">Opening Times</a></li> <li class="dropdown-submenu-item"><a href="#">Contact Us</a></li> </ul> </dd> </div> <div> <dt class="dropdown-menu-item-title">Three</dt> <dd class="dropdown-menu-item-data hide"> <ul class="dropdown-submenu"> <li class="dropdown-submenu-item"><a href="#">About Us</a></li> <li class="dropdown-submenu-item"><a href="#">Visit Us</a></li> <li class="dropdown-submenu-item"><a href="#">Contact Us</a></li> </ul> </dd> </div> </dl> </div>


延伸阅读:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM