Używam bootstrap i chciałbym dodać animację do listy rozwijanej. Chcę dodać do niego animację, zjeżdżać w dół i cofać się, gdy ją opuszczam. Jak mogłem to zrobić?
Rzeczy, które próbowałem:
Zmiana rozwijanego pliku Js w następujący sposób:
Jak mogę sprawić, aby menu rozwijane nawigacji Bootstrap przesuwały się płynnie w górę iw dół?
javascript
drop-down-menu
twitter-bootstrap
Ben Beri
źródło
źródło
Odpowiedzi:
Jeśli zaktualizujesz Bootstrap 3 (BS3), ujawnili wiele zdarzeń Javascript, z którymi przyjemnie jest powiązać pożądaną funkcjonalność. W BS3 ten kod nada wszystkim rozwijanym menu efekt animacji, którego szukasz:
// 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(); });
Możesz przeczytać o wydarzeniach BS3 tutaj, a konkretnie o wydarzeniach rozwijanych tutaj .
źródło
hidden.bs.dropdown
zdarzenia.Można również uniknąć używania JavaScript do rozwijania efektu i użyć przejścia CSS3, dodając ten mały fragment kodu do swojego stylu:
.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; }
Jedynym problemem związanym z tym sposobem jest ręczne określenie maksymalnej wysokości. Jeśli ustawisz bardzo dużą wartość, Twoja animacja będzie bardzo szybka.
Działa to jak urok, jeśli znasz przybliżoną wysokość swoich list rozwijanych, w przeciwnym razie nadal możesz użyć javascript, aby ustawić dokładną wartość maksymalnej wysokości.
Oto mały przykład: DEMO
! W tym rozwiązaniu jest mały błąd z dopełnieniem, sprawdź komentarz Jacoba Stamm'a z rozwiązaniem.
źródło
pointer-events:none
do zwiniętej wersji, a następnie dodaćpoint-events: all
do menu, gdy już ma.show
Robię coś takiego, ale po najechaniu kursorem zamiast kliknięciu .. To jest kod, którego używam, możesz go nieco poprawić, aby działał po kliknięciu
$('.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() });
źródło
<script>
tagami, ale nic się nie stałoNie wiem, czy mogę podnieść ten wątek, ale znalazłem szybką naprawę wizualnego błędu, który występuje, gdy klasa otwarta jest usuwana zbyt szybko. Zasadniczo wystarczy dodać funkcję OnComplete do zdarzenia slideUp i zresetować wszystkie aktywne klasy i atrybuty. Idzie mniej więcej tak:
Oto wynik: przykład Bootply
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'); }); }); });
źródło
oto moje rozwiązanie dla efektu slide & fade:
// 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:''}); }); });
źródło
$(this).css({'margin-top':''});
@VedmantZaktualizuj 2018 Bootstrap 4
W Boostrap 4
.open
klasa została zastąpiona przez.show
. Chciałem to zaimplementować używając tylko tranzystorów CSS bez potrzeby dodatkowego JS lub 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; }
Demo: https://www.codeply.com/go/3i8LzYVfMF
Uwaga:
max-height
można ustawić dowolną dużą wartość, która wystarczy, aby pomieścić zawartość rozwijanego menu.źródło
margin-top
.Po kliknięciu można to zrobić za pomocą poniższego kodu
$('.dropdown-toggle').click(function() { $(this).next('.dropdown-menu').slideToggle(500); });
źródło
Używam powyższego kodu, ale zmieniłem efekt opóźnienia przez slideToggle.
Przesuwa menu po najechaniu kursorem z animacją.
$('.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) });
źródło
Rozszerzona odpowiedź była moją pierwszą odpowiedzią, więc wymówką, jeśli wcześniej nie było wystarczająco dużo szczegółów.
W przypadku Bootstrap 3.x osobiście preferuję animacje CSS i używam animate.css i razem z hakami JavaScript w Bootstrap Dropdown. Chociaż może nie mieć dokładnie takiego efektu, jakiego szukasz, jest to dość elastyczne podejście.
Krok 1: Dodaj animate.css do swojej strony za pomocą tagów head:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.4.0/animate.min.css">
Krok 2: Użyj standardowego kodu HTML Bootstrap na wyzwalaczu:
<div class="dropdown"> <button type="button" data-toggle="dropdown">Dropdown trigger</button> <ul class="dropdown-menu"> ... </ul> </div>
Krok 3: Następnie dodaj 2 niestandardowe atrybuty danych do elementu dropdrop-menu; menu rozwijane danych dla animacji wejściowej i menu rozwijane danych dla animacji wyjściowej. Mogą to być dowolne efekty animate.css, takie jak fadeIn lub fadeOut
<ul class="dropdown-menu" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut"> ...... </ul>
Krok 4: Następnie dodaj następujący kod JavaScript, aby odczytać atrybuty danych wchodzących / wychodzących z listy rozwijanej i reagować na zaczepy / zdarzenia interfejsu 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'); }); } }, });
Krok 5 (opcjonalnie): Jeśli chcesz przyspieszyć lub zmienić animację, możesz to zrobić za pomocą CSS w następujący sposób:
.dropdown-menu.animated { /* Speed up animations */ -webkit-animation-duration: 0.55s; animation-duration: 0.55s; -webkit-animation-timing-function: ease; animation-timing-function: ease; }
Napisałem artykuł zawierający więcej szczegółów i plik do pobrania, jeśli ktoś jest zainteresowany: artykuł: http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss
Mam nadzieję, że to pomocne, a ten drugi artykuł ma poziom szczegółowości potrzebny Tomowi
źródło
$('.navbar .dropdown').hover(function() { $(this).find('.dropdown-menu').first().stop(true, true).slideDown(); }, function() { $(this).find('.dropdown-menu').first().stop(true, true).slideUp(); });
Ten kod działa, jeśli chcesz wyświetlać listy rozwijane po najechaniu kursorem.
Właśnie zmienił
.slideToggle
się.slideDown
i.slideUp
, i usunął(400)
rozrząduźródło
Oto ładne proste rozwiązanie,
jQuery
które działa ładnie:$('.dropdown-toggle').click(function () { $(this).next('.dropdown-menu').slideToggle(300); }); $('.dropdown-toggle').focusout(function () { $(this).next('.dropdown-menu').slideUp(300); })
Przełączanie animacji slajdu następuje po kliknięciu i zawsze przesuwa się w górę po utracie ostrości.
Zmień
300
wartość na dowolną, im niższa liczba, tym szybsza animacja.Edytować:
To rozwiązanie będzie działać tylko w przypadku widoków pulpitu. Będzie wymagać dalszych modyfikacji, aby ładnie wyświetlać się na urządzeniach mobilnych.
źródło
dropdown-toggle
) ponownie znika, co oznacza, że nie mogę wybrać elementów podmenuBOOTSTRAP 3 REFERENCE
Dodano, ponieważ rozwiązanie w tym wątku łapie mnie i za każdym razem mnie to napycha.
Zasadniczo lista rozwijana BS natychmiast usuwa rozszerzenie
.open
klasę z rodzica, więc przesuwanie się nie działa.Użyj tego samego bitu, co inne rozwiązania dla slideDown ();
// 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'); }); });
źródło
Intro
W chwili pisania tego tekstu oryginalna odpowiedź ma 8 lat. Wciąż czuję, że nie ma jeszcze właściwego rozwiązania pierwotnego pytania.
Od tamtej pory Bootstrap przeszedł długą drogę i jest teraz na poziomie 4.5.2 . Ta odpowiedź dotyczy właśnie tej wersji.
Problem ze wszystkimi dotychczasowymi rozwiązaniami
Problem ze wszystkimi innymi odpowiedziami polega na tym, że podczas podłączania się do
show.bs.dropdown
/hide.bs.dropdown
, zdarzenia następczeshown.bs.dropdown
/hidden.bs.dropdown
są albo uruchamiane zbyt wcześnie (animacja nadal trwa), albo w ogóle nie odpalają, ponieważ zostały stłumione (e.preventDefault()
).Czyste rozwiązanie
Ponieważ implementacja
show()
iw klasiehide()
BootstrapsDropdown
ma pewne podobieństwa, zgrupowałem je razemtoggleDropdownWithAnimation()
podczas naśladowania oryginalnego zachowania i dodałem małe funkcje pomocnicze QoL doshowDropdownWithAnimation()
ihideDropdownWithAnimation()
.toggleDropdownWithAnimation()
tworzyshown.bs.dropdown
/hidden.bs.dropdown
zdarzenie w taki sam sposób, jak robi to Bootstrap. To zdarzenie jest następnie uruchamiane po zakończeniu animacji - tak, jak można się spodziewać./** * 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); }
Bind Event Listeners
Teraz, gdy napisaliśmy odpowiednie wywołania zwrotne do pokazywania / ukrywania listy rozwijanej z animacją, powiążmy je z odpowiednimi zdarzeniami.
Częstym błędem, który widziałem wiele w innych odpowiedziach, jest bezpośrednie wiązanie detektorów zdarzeń z elementami. Chociaż działa to dobrze w przypadku elementów DOM obecnych w momencie rejestracji detektora zdarzeń, nie wiąże się to z elementami dodanymi później.
Dlatego generalnie lepiej jest wiązać bezpośrednio z
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)); }); });
źródło
W przypadku Bootstrap 3 ta odmiana powyższych odpowiedzi sprawia, że
slideUp()
animacja mobilna jest płynniejsza; powyższe odpowiedzi mają przerywaną animację, ponieważ Bootstrap.open
natychmiast usuwa klasę z elementu nadrzędnego przełącznika, więc ten kod przywraca klasę do zakończeniaslideUp()
animacji.// 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'); });
Kluczowe różnice:
hide.bs.dropdown
obsługi zdarzeń używam.stop()
domyślnej wartości (false
) jako drugiego argumentu (jumpToEnd
)hidden.bs.dropdown
obsługi zdarzeń przywraca.open
klasę do elementu nadrzędnego przełącznika rozwijanego i robi to prawie natychmiast po pierwszym usunięciu klasy. W międzyczasieslideUp()
animacja nadal działa i tak jak w odpowiedziach powyżej, jej wywołanie zwrotne „animacja-zakończona” jest odpowiedzialne za ostateczne usunięcie.open
klasy z jej rodzica.źródło