将幻灯片效果添加到引导下拉列表

Adding a slide effect to bootstrap dropdown

本文关键字:下拉列表 添加 幻灯片      更新时间:2023-09-26

我正在使用引导程序,我想在下拉列表中添加动画。我想给它添加一个动画,离开它时向下滑动和向上滑动。我该怎么做?

我尝试过的事情:

像这样更改 Js 下拉文件:

如何使 Bootstrap 的导航下拉平滑地上下滑动?

如果你更新到Bootstrap 3(BS3(,它们已经暴露了很多Javascript事件,这些事件非常适合将你想要的功能绑定到其中。 在BS3中,此代码将为您提供所有下拉菜单所需的动画效果:

  // Add slideDown animation to Bootstrap dropdown when expanding.
  $('.dropdown').on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
  });
  // Add slideUp animation to Bootstrap dropdown when collapsing.
  $('.dropdown').on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
  });

您可以在此处阅读有关 BS3 事件的信息,特别是有关下拉事件的信息 此处.

此外,还可以通过将这一小段代码添加到您的样式中来避免使用 JavaScript 来实现下拉效果,并使用 CSS3 过渡:

.dropdown .dropdown-menu {
    -webkit-transition: all 0.3s;
    -moz-transition: all 0.3s;
    -ms-transition: all 0.3s;
    -o-transition: all 0.3s;
    transition: all 0.3s;
    max-height: 0;
    display: block;
    overflow: hidden;
    opacity: 0;
}
.dropdown.open .dropdown-menu { /* For Bootstrap 4, use .dropdown.show instead of .dropdown.open */
    max-height: 300px;
    opacity: 1;
}

这种方式的唯一问题是您应该手动指定最大高度。如果设置了一个非常大的值,则动画将非常快。

如果您知道下拉列表的大致高度,它就像一个魅力,否则您仍然可以使用 javascript 来设置精确的最大高度值。

下面是一个小例子:演示


!此解决方案中的填充存在小错误,请查看雅各布·斯塔姆(Jacob Stamm(对解决方案的评论。

我正在做类似的事情,但是悬停而不是单击。这是我正在使用的代码,您也许可以对其进行一些调整以使其在单击时工作

$('.navbar .dropdown').hover(function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(100).slideUp()
});

我不知道我是否可以碰到这个线程,但是我想出了快速解决打开类删除太快时发生的视觉错误的方法。基本上,它所做的只是在slideUp事件中添加一个OnComplete函数并重置所有活动类和属性。是这样的:

结果如下:引导示例

Javascript/Jquery:

$(function(){
    // ADD SLIDEDOWN ANIMATION TO DROPDOWN //
    $('.dropdown').on('show.bs.dropdown', function(e){
        $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
    });
    // ADD SLIDEUP ANIMATION TO DROPDOWN //
    $('.dropdown').on('hide.bs.dropdown', function(e){
        e.preventDefault();
        $(this).find('.dropdown-menu').first().stop(true, true).slideUp(400, function(){
            //On Complete, we reset all active dropdown classes and attributes
            //This fixes the visual bug associated with the open class being removed too fast
            $('.dropdown').removeClass('show');
            $('.dropdown-menu').removeClass('show');
            $('.dropdown').find('.dropdown-toggle').attr('aria-expanded','false');
        });
    });
});

这是我对滑动和淡入淡出效果的解决方案:

   // Add slideup & fadein animation to dropdown
   $('.dropdown').on('show.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}).animate({'margin-top': orig_margin_top + 'px', opacity: 1}, 300, function(){
         $(this).css({'margin-top':''});
      });
   });
   // Add slidedown & fadeout animation to dropdown
   $('.dropdown').on('hide.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': orig_margin_top + 'px', opacity: 1, display: 'block'}).animate({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}, 300, function(){
         $(this).css({'margin-top':'', display:''});
      });
   });

更新 2018 引导程序 4

在 Boostrap 4 中,.open类已被替换为 .show 。我想只使用CSS转换来实现这一点,而不需要额外的JS或jQuery......

.show > .dropdown-menu {
  max-height: 900px;
  visibility: visible;
}
.dropdown-menu {
  display: block;
  max-height: 0;
  visibility: hidden;
  transition: all 0.5s ease-in-out;
  overflow: hidden;
}

演示:https://www.codeply.com/go/3i8LzYVfMF

注意:max-height可以设置为足以容纳下拉内容的任何大值。

单击时可以使用以下代码完成

$('.dropdown-toggle').click(function() {
  $(this).next('.dropdown-menu').slideToggle(500);
});

我正在使用上面的代码,但我通过 slideBangle 更改了延迟效果。

它会在悬停动画时滑动下拉列表。

$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400);
    }, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400)
    });

对于 Bootstrap 5,可以使用简单的 keframe 动画完成简单而漂亮的动画幻灯片。

@keyframes slideIn {
    0% {
        transform: translateY(1rem);
        opacity: 0;
    }
    100% {
        transform: translateY(0rem);
        opacity: 1;
    }
}
.slideIn {
    -webkit-animation-name: slideIn;
    animation-name: slideIn;
    animation-duration: 0.4s;
    animation-fill-mode: both;
}
<li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle m-2" href="/" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Dropdown
          </a>
          <ul class="dropdown-menu slideIn rounded-2 p-3" aria-labelledby="navbarDropdown">
            <li><a class="dropdown-item" href="/">Action</a></li>
            <li><a class="dropdown-item" href="/">Another action</a></li>
            <li><hr class="dropdown-divider"/></li>
            <li><a class="dropdown-item" href="/">Something else here</a></li>
          </ul>
        </li>

扩展答案,是我的第一个答案,所以如果之前没有足够的细节,请原谅。

对于Bootstrap

3.x,我个人更喜欢CSS动画,我一直在使用animate.css以及Bootstrap Dropdown Javascript Hooks。尽管它可能没有您所追求的确切效果,但这是一种非常灵活的方法。

第 1 步:使用 head 标签将 animate.css 添加到您的页面:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.4.0/animate.min.css">

第 2 步:在触发器上使用标准的引导 HTML:

<div class="dropdown">
  <button type="button" data-toggle="dropdown">Dropdown trigger</button>
  <ul class="dropdown-menu">
    ...
  </ul>
</div>

第三步: 然后将 2 个自定义数据属性添加到下拉菜单元素; 数据下拉用于输入动画,数据下拉用于输出动画。这些可以是任何动画效果.css如淡入或淡出

<ul class="dropdown-menu" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut">
......
</ul>

第 4 步:接下来添加以下 Javascript 来读取数据下拉输入/输出数据属性并响应 Bootstrap Javascript API 钩子/事件 (http://getbootstrap.com/javascript/#dropdowns-events(:

var dropdownSelectors = $('.dropdown, .dropup');
// Custom function to read dropdown data
// =========================
function dropdownEffectData(target) {
  // @todo - page level global?
  var effectInDefault = null,
      effectOutDefault = null;
  var dropdown = $(target),
      dropdownMenu = $('.dropdown-menu', target);
  var parentUl = dropdown.parents('ul.nav'); 
  // If parent is ul.nav allow global effect settings
  if (parentUl.size() > 0) {
    effectInDefault = parentUl.data('dropdown-in') || null;
    effectOutDefault = parentUl.data('dropdown-out') || null;
  }
  return {
    target:       target,
    dropdown:     dropdown,
    dropdownMenu: dropdownMenu,
    effectIn:     dropdownMenu.data('dropdown-in') || effectInDefault,
    effectOut:    dropdownMenu.data('dropdown-out') || effectOutDefault,  
  };
}
// Custom function to start effect (in or out)
// =========================
function dropdownEffectStart(data, effectToStart) {
  if (effectToStart) {
    data.dropdown.addClass('dropdown-animating');
    data.dropdownMenu.addClass('animated');
    data.dropdownMenu.addClass(effectToStart);    
  }
}
// Custom function to read when animation is over
// =========================
function dropdownEffectEnd(data, callbackFunc) {
  var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
  data.dropdown.one(animationEnd, function() {
    data.dropdown.removeClass('dropdown-animating');
    data.dropdownMenu.removeClass('animated');
    data.dropdownMenu.removeClass(data.effectIn);
    data.dropdownMenu.removeClass(data.effectOut);
    // Custom callback option, used to remove open class in out effect
    if(typeof callbackFunc == 'function'){
      callbackFunc();
    }
  });
}
// Bootstrap API hooks
// =========================
dropdownSelectors.on({
  "show.bs.dropdown": function () {
    // On show, start in effect
    var dropdown = dropdownEffectData(this);
    dropdownEffectStart(dropdown, dropdown.effectIn);
  },
  "shown.bs.dropdown": function () {
    // On shown, remove in effect once complete
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectIn && dropdown.effectOut) {
      dropdownEffectEnd(dropdown, function() {}); 
    }
  },  
  "hide.bs.dropdown":  function(e) {
    // On hide, start out effect
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectOut) {
      e.preventDefault();   
      dropdownEffectStart(dropdown, dropdown.effectOut);   
      dropdownEffectEnd(dropdown, function() {
        dropdown.dropdown.removeClass('open');
      }); 
    }    
  }, 
});

第 5 步(可选(:如果要加快或更改动画,可以使用 CSS 进行,如下所示:

.dropdown-menu.animated {
  /* Speed up animations */
  -webkit-animation-duration: 0.55s;
  animation-duration: 0.55s;
  -webkit-animation-timing-function: ease;
  animation-timing-function: ease;
}

写了一篇更详细的文章,如果有人感兴趣,可以下载:文章: http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss

希望这是有帮助的,这第二篇文章具有所需的详细程度汤姆

简介

截至撰写本文时,原始答案现已 8 岁。我仍然觉得原始问题还没有适当的解决方案。

从那时起,Bootstrap 已经走了很长一段路,现在是 4.5.2。这个答案解决了这个版本。

到目前为止所有其他解决方案的问题

所有其他答案的问题在于,当它们连接到show.bs.dropdown/hide.bs.dropdown时,后续事件shown.bs.dropdown/hidden.bs.dropdown要么过早触发(动画仍在进行中(,要么它们根本不触发,因为它们被抑制了(e.preventDefault()(。

清洁的解决方案

由于 Bootstraps Dropdown类中 show()hide() 的实现有一些相似之处,因此我在toggleDropdownWithAnimation()模仿原始行为时将它们分组在一起,并在 showDropdownWithAnimation()hideDropdownWithAnimation() .
中添加了少量的 QoL 帮助程序函数 toggleDropdownWithAnimation()创建shown.bs.dropdown/hidden.bs.dropdown事件的方式与引导程序相同。然后,此事件将在动画完成后触发 - 就像您所期望的那样。

/**
 * Toggle visibility of a dropdown with slideDown / slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {boolean} show Show (true) or hide (false) the dropdown menu.
 * @param {number} duration Duration of the animation in milliseconds
 */
function toggleDropdownWithAnimation($containerElement, show, duration = 300): void {
    // get the element that triggered the initial event
    const $toggleElement = $containerElement.find('.dropdown-toggle');
    // get the associated menu
    const $dropdownMenu = $containerElement.find('.dropdown-menu');
    // build jquery event for when the element has been completely shown
    const eventArgs = {relatedTarget: $toggleElement};
    const eventType = show ? 'shown' : 'hidden';
    const eventName = `${eventType}.bs.dropdown`;
    const jQueryEvent = $.Event(eventName, eventArgs);
    if (show) {
        // mimic bootstraps element manipulation
        $containerElement.addClass('show');
        $dropdownMenu.addClass('show');
        $toggleElement.attr('aria-expanded', 'true');
        // put focus on initial trigger element
        $toggleElement.trigger('focus');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .hide() // hide element to fix initial state of element for slide down animation
            .slideDown(duration, () => {
            // fire 'shown' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
    else {
        // mimic bootstraps element manipulation
        $containerElement.removeClass('show');
        $dropdownMenu.removeClass('show');
        $toggleElement.attr('aria-expanded', 'false');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .show() // show element to fix initial state of element for slide up animation
            .slideUp(duration, () => {
            // fire 'hidden' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
}
/**
 * Show a dropdown with slideDown animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function showDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, true, duration);
}
/**
 * Hide a dropdown with a slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function hideDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, false, duration);
}

绑定事件侦听器

现在我们已经编写了正确的回调来显示/隐藏带有动画的下拉列表,让我们实际将这些回调绑定到正确的事件。

我在其他答案中看到的一个常见错误是将事件侦听器直接绑定到元素。虽然这对于注册事件侦听器时存在的 DOM 元素工作正常,但它不会绑定到稍后添加的元素。

这就是为什么您通常最好直接绑定到document

$(function () {
    /* Hook into the show event of a bootstrap dropdown */
    $(document).on('show.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
        
        showDropdownWithAnimation($(this));
    });
    /* Hook into the hide event of a bootstrap dropdown */
    $(document).on('hide.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
          
        hideDropdownWithAnimation($(this));
    });
});
$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
}, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
});

如果要在悬停时显示下拉列表,则此代码有效。

我只是将.slideToggle更改为.slideDown&.slideUp,并删除了(400)时间

这是一个很好的简单解决方案,使用 jQuery 运行良好:

$('.dropdown-toggle').click(function () {
    $(this).next('.dropdown-menu').slideToggle(300);
});
$('.dropdown-toggle').focusout(function () {
    $(this).next('.dropdown-menu').slideUp(300);
})

幻灯片动画切换在单击时发生,并且在失去焦点时始终向上滑动。

300值更改为所需的任何值,数字越小,动画速度越快。

编辑:

此解决方案仅适用于桌面视图。它需要进一步修改才能在移动设备上很好地显示。

我建议使用transform而不是max-height,它更快,GPU加速。

对于 Bootstrap 5,添加以下 CSS:

 .dropdown .dropdown-menu {
    -webkit-transition: all 0.32s;
    -moz-transition: all 0.32s;
    -ms-transition: all 0.32s;
    -o-transition: all 0.32s;
    transition: all 0.32s;
    display: block;
    overflow: hidden;
    opacity: 0;
    transform: translateX(-25%) scaleY(0);
    transform-origin: top;
  }
  .dropdown-menu.show {
    opacity: 1;
    transform: translateX(-25%) scaleY(1);
  }

引导程序 3 参考

添加是因为我一直被这个线程中的解决方案所吸引,每次它都会塞满我。

基本上,BS 下拉列表会立即从父级中删除 .open 类,因此向上滑动不起作用。

使用与其他解决方案相同的位来滑动((;

// ADD SLIDEUP ANIMATION TO DROPDOWN //
$('.dropdown').on('hide.bs.dropdown', function(e){
  e.preventDefault();
  $(this).find('.dropdown-menu').first().stop(true, true).slideUp(300, function(){
    $(this).parent().removeClass('open');
  });
});
对于 Bootstrap 3,上述答案的

这种变化使移动slideUp()动画更加流畅;上面的答案有断断续续的动画,因为 Bootstrap 会立即从切换的父级中删除.open类,因此此代码会还原该类,直到slideUp()动画完成。

// Add animations to topnav dropdowns
// based on https://stackoverflow.com/a/19339162
// and https://stackoverflow.com/a/52231970
$('.dropdown')
  .on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
  })
  .on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, false).slideUp(300, function() {
      $(this).parent().removeClass('open');
    });
  })
  .on('hidden.bs.dropdown', function() {
    $(this).addClass('open');
  });

主要区别:

  • hide.bs.dropdown事件处理程序中,我使用 .stop() 的默认值 ( false ( 作为其第二个参数 ( jumpToEnd (
  • hidden.bs.dropdown 事件处理程序将 .open 类还原到下拉列表切换的父级,并且在首次删除类后几乎立即执行此操作。同时,slideUp()动画仍在运行,就像上面的答案一样,它的"动画已完成"回调负责最终从其父级中删除.open类。
  • 方法链接在一起,因为每个事件处理程序的选择器相同
 $(this).find('.dropdown-menu').first().stop(true, true).slideUp(300, function(){
    $(this).parent().removeClass('open');
  });

我刚刚用 .slideSwitchgle替换了 .slideUp,它上下工作正常。

这对我来说很好用。

 .dropdown-menu {
    transition: all linear .5s;
}
.dropdown-menu.show {
    display: block;
    transition: all linear .5s;
}

它适用于 Bootstrap 5 和 React-Bootstrap...

.dropdown-menu {
        display: block;
        transform-origin: top;
        transform: scaleY(0);
        opacity: 0;
        overflow: hidden;
        transition: all 0.3s ease-in-out;
        -webkit-transition: all 0.3s ease-in-out;
    }
    
    .dropdown.show .dropdown-menu { 
        opacity: 1;
        transform: scaleY(1);
        overflow: visible;
    }