wyłącz nganimate dla niektórych elementów

96

Używam moduł ngAnimate, ale wszystkie moje ng-if, ng-showitp, są dotknięte, że chcę wykorzystać ngAnimate dla wybranych elementów. Ze względu na wydajność i kilka błędów w elementach, które pokazują i ukrywają się bardzo szybko.

dzięki.

drtobal
źródło
1
Dodaj przykładowy kod problemu.
cheekybastard
Jednym z problemów jest to, że ngAnimate wymusza display:blockna wszystkich twoich przemiennikach:ng-hide-add-active, .ng-hide-remove { display: block!important; }
Somatik
Lepszym pytaniem, które można by zadać, byłoby „jak zdefiniować mój CSS, aby ngAnimate działał poprawnie dla elementów, które są ukryte bez wykonywania pełnej pętli animacji”. Najlepsza odpowiedź pochodzi od Chrisa Barra poniżej.
Eric

Odpowiedzi:

53

Po prostu dodaj to do swojego CSS. Najlepiej, jeśli jest to ostatnia zasada:

.no-animate {
   -webkit-transition: none !important;
   transition: none !important;
}

następnie dodaj no-animatedo klasy elementu, który chcesz wyłączyć. Przykład:

<div class="no-animate"></div>
David Addoteye
źródło
2
Jeśli używasz sass, nie potrzebujesz opcji „-webkit-przejście: brak! Ważne;”
Marwen Trabelsi
15
Zwróć uwagę, że ta odpowiedź jest błędna, ponieważ WYŁĄCZA WSZYSTKIE ANIMACJE, a nie tylko te, które są obsługiwane przez Angular.
stackular
1
Próbowałeś tego? pokaż mi przykład twojego kodu. Działa dla mnie i dla ponad sześciu osób, które go zatwierdziły
David Addoteye
2
Dodałem .no-animate, .no-animate-children *regułę dotyczącą dzieci itp.
Kimball Robinson
1
@DavidAddoteye to rozwiązanie nie jest wykonalne, jeśli masz ng-show lub ng-if nad elementem z przejściem .. to znaczy ... jeśli mam spinner modułu ładującego, który pojawia się tylko podczas żądania http i znika, gdy żądanie zostanie rozwiązane, dodanie ta klasa w ogóle nie spowoduje animacji !, odpowiedź michaela jest w porządku, ale zbyt żmudna do implementacji, i powinieneś unikać selektorów css w kontrolerach. Utworzenie dyrektywy jest OK, ale patrząc na odpowiedź Blowsiego, okaże się, że zespół AngularJS zapewnił już elastyczny sposób na rozwiązanie tego problemu;)
edrian
106

Jeśli chcesz włączyć animacje dla określonych elementów ( zamiast wyłączać je dla określonych elementów), możesz użyć $ animateProvider do skonfigurowania elementów o określonej nazwie klasy (lub wyrażeniu regularnym) do animacji.

Poniższy kod włączy animacje dla elementów posiadających angular-animateklasę:

var myApp = angular.module("MyApp", ["ngAnimate"]);
myApp.config(function($animateProvider) {
  $animateProvider.classNameFilter(/angular-animate/);
})

Oto przykładowe znaczniki zawierające angular-animateklasę włączającą animacje:

<div ng-init="items=[1,2,3,4,5,6,7,8,9]">
  <input placeholder="Filter with animations." ng-model="f" /> 
  <div class="my-repeat-animation angular-animate" ng-repeat="item in items | filter:f track by item" >
    {{item}}
  </div>
</div>

Przykład Plunkera zapożyczony i zmodyfikowany z tego bloga, gdzie tylko pierwszy filtr zawiera animacje (ze względu na posiadanie angular-animateklasy).

Zwróć uwagę, że używam angular-animatejako przykładu i jest on całkowicie konfigurowalny za pomocą .classNameFilterfunkcji.

Gloopy
źródło
5
Uratowałeś mi dzień. Dziękuję bardzo
gustavohenke
Jest to najbardziej eleganckie rozwiązanie, ponieważ wymaga zgody na animacje, a animowane elementy są wyraźnie odróżniane od innych według nazwy klasy.
Nikola M.
2
To powinno być przyjęte rozwiązanie. Działa idealnie i uratował mi dzień!
9
użyj /^(?:(?!ng-animate-disabled).)*$/wyrażenia regularnego, aby wyłączyć anulowanie z ng-animate-disabledklasą.
IcanDivideBy0
Świetne rozwiązanie! Mam tabelę podzieloną na strony z 20 wierszami na stronę. Trzecia część czasu na przełączanie stron była pochłaniana przez przeglądarkę przetwarzającą klasy animacji css, które nawet nie były używane.
Kevin
81

Istnieją dwa sposoby na rozłączenie animacji w AngularJS, jeśli masz moduł ngAnimate jako zależność od swojego modułu:

  1. Wyłącz lub włącz animację globalnie w usłudze $ animate:

    $animate.enabled(false);
  2. Wyłącz animacje dla konkretnego elementu - musi to być element dla tego angulara doda klasy css Animationstate (np. Ng-enter, ...)!

    $animate.enabled(false, theElement);

Od wersji Angular 1.4 należy odwrócić argumenty:

$animate.enabled(theElement, false);

Dokumentacja dla$animate .

Michael
źródło
2
To nie działa w przypadku określonych elementów zgodnie z oczekiwaniami. Jeśli wyłączę animacje globalnie, a następnie włączę je na jednym konkretnym elemencie, to nie działa.
Kushagra Gour
1
Tę odpowiedź należy usunąć lub zmodyfikować, aby określić, na której wersji Angulara faktycznie działa. W przypadku wersji 1.2.10 zdecydowanie nie działa w przypadku selektywnego włączania animacji dla niektórych elementów, o co chodzi w pytaniu AFAICT.
Trindaz
Czy ktoś wie, czy opcja 2 działa na wersji 1.2.25?
khorvat
1
Wystarczy spojrzeć na dokumentację ( docs.angularjs.org/api/ng/service/$animate ) i wydaje się, że „element” jest pierwszym parametrem przekazywanym do włączonej funkcji.
DanielM
49

Aby wyłączyć ng-animate dla niektórych elementów, używając klasy CSS, która jest zgodna z paradygmatem Angular animate, możesz skonfigurować ng-animate do testowania klasy przy użyciu wyrażenia regularnego.

Config

    var myApp = angular.module("MyApp", ["ngAnimate"]);
    myApp.config(function($animateProvider) {
        $animateProvider.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/);
    })

Stosowanie

Po prostu dodaj ng-animate-disabledklasę do wszystkich elementów, które chcesz ignorować przez ng-animate.


Kredyt http://davidchin.me/blog/disable-nganimate-for-selected-elements/

Blowsie
źródło
7
Myślę, że jest to najbardziej poprawny sposób filtrowania zachowania ngannimate!
edrian
6
Warto było przewijać tę odpowiedź.
Jossef Harush
Mogę potwierdzić, że w najnowszej wersji AngularJS jest to zdecydowanie najlepsze rozwiązanie problemu.
Adam Reis
44

dzięki, napisałem dyrektywę, którą możesz umieścić na elemencie

CoffeeScript:

myApp.directive "disableAnimate", ($animate) ->
  (scope, element) ->
    $animate.enabled(false, element)

JavaScript:

myApp.directive("disableAnimate", function ($animate) {
    return function (scope, element) {
        $animate.enabled(false, element);
    };
});
user1750709
źródło
To całkiem sprytne podejście, nie zawsze jest jasne, jak uzyskać dostęp do obiektu elementu, a przy niektórych innych podejściach obawiam się, że zaśmiecałbym moje kontrolery za pomocą skryptu JavaScript odwołującego się do jednego lub kilku elementów zdefiniowanych w szablonie . To jak wielkie rozdzielenie obaw, chwała!
Mattygabe
2
Kolejność parametrów jest odwrócona w $ animate.enabled, jeśli ktoś się zastanawia, dlaczego to wyłącza całą animację ng. Działa jak urok, jeśli używasz$animate.enabled(element,false);
gss
Przepraszam, widzę, że dotyczy to tylko wersji 1.4.x +, powyższy kod jest poprawny dla poprzednich wersji.
gss
19

Odkryłem, że $animate.enabled(false, $element);będzie działać dla elementów, które używają ng-showlub, ng-hideale nie będzie działać dla elementów, które używają ng-ifz jakiegoś powodu! Rozwiązanie, które ostatecznie wykorzystałem, polegało na zrobieniu tego wszystkiego w CSS, czego nauczyłem się z tego wątku na GitHubie .

CSS

/* Use this for transitions */
.disable-animations.ng-enter,
.disable-animations.ng-leave,
.disable-animations.ng-animate {
  -webkit-transition: none !important;
  transition: none !important;
}

/* Use this for keyframe animations */
.disable-animations.ng-animate {
  -webkit-animation: none 0s;
  animation: none 0s;
}

SCSS

.disable-animations {
  // Use this for transitions
  &.ng-enter,
  &.ng-leave,
  &.ng-animate {
    -webkit-transition: none !important;
    transition: none !important;
  }
  // Use this for keyframe animations
  &.ng-animate {
    -webkit-animation: none 0s;
    animation: none 0s;
  }
}
CBarr
źródło
Mój przypadek był taki, że po załadowaniu ngAnimate klasa taka jak .loading.ng-hide pozostawała na ekranie do zakończenia pełnej pętli animacji. To najczystsza odpowiedź, ponieważ po prostu przekazuje odpowiednią konfigurację do ngAnimate i używa jej normalnie. Jest to lepsze niż błędna konfiguracja, a następnie wyłączenie. Więc +1 dla ciebie, żałuję, że nie mogę dać więcej, aby wyrównać wynik tutaj.
Eric
To najtrudniejsza odpowiedź. Robienie tego z css jest lepsze niż majstrowanie przy js.
manas
Proszę spojrzeć na odpowiedź @Blowsie, czyli bardziej ogólny i poprawny sposób radzenia sobie z tym
edrian
3

Ja nie chce używać ngAnimate na moich ng-if„s, więc byłoby to moje rozwiązanie:

[ng-if] {
  .ng-enter, .ng-leave, .ng-animate {
    -webkit-transition: none !important;
    transition: none !important;
  }
}

Po prostu zamieszczam to jako kolejną sugestię!

Betty St
źródło
2

Mam listę, z której pierwszy lijest ukryty za pomocą ng-hide="$first". Użycie ng-enterskutkuje lipokazaniem się przez pół sekundy przed zniknięciem.

W oparciu o rozwiązanie Chrisa Barra mój kod wygląda teraz następująco:

HTML

<ol>
    <li ng-repeat="item in items"
        ng-hide="$first"
        ng-class="{'no-animate' : $first}">
    </li>
</ol>

CSS

.no-animate.ng-enter,
.no-animate.ng-leave,
.no-animate.ng-animate {
        transition: none !important; /* disable transitions */
        animation: none 0s !important; /* disable keyframe animations */
}

li.ng-enter {
    opacity: 0;
    transition: opacity 0.3s ease-out;
}
li.ng-enter-active {
    opacity: 1;
}

/* I use Autoprefixer. If you don't, please include vendor prefixes. */
robro
źródło
0

Wiem, że to opóźniona odpowiedź, ale tutaj używamy w MainController:

// disable all animations
$animate.enabled(false);

Ale problem polega na tym, że kiedy wyłączamy wszystkie animacje, konfiguracja interfejsu użytkownika jest tak skonfigurowana opacity: 0.

Dlatego konieczne jest ustawienie krycia na 1 za pomocą CSS:

.ui-select-choices {
    opacity: 1 !important;
}

Spowoduje to prawidłowe ustawienie krycia, a ui-select zadziała.

David Branco
źródło