desabilitar nganimado para alguns elementos

96

Estou usando o módulo ngAnimate, mas toda a minha ng-if, ng-show, etc, são afetados por isso, eu quero alavancagem ngAnimate para alguns elementos selecionados. Para desempenho e alguns bugs em elementos que se mostram e se escondem muito rápidos.

obrigado.

drtobal
fonte
1
Adicione algum código de exemplo do problema.
cheekybastard de
Um dos problemas é que o ngAnimate força display:blockem todos os seus repetidores:ng-hide-add-active, .ng-hide-remove { display: block!important; }
Somatik
A melhor pergunta a fazer seria "como posso definir meu CSS para fazer o ngAnimate funcionar corretamente para elementos que estão ocultos sem completar um loop de animação completo". A melhor resposta é de Chris Barr abaixo.
Eric,

Respostas:

53

Basta adicionar isso ao seu CSS. É melhor se for a última regra:

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

em seguida, adicione no-animateà classe de elemento que deseja desativar. Exemplo:

<div class="no-animate"></div>
David Addoteye
fonte
2
Se você estiver usando ousadia, não precisa do "-webkit-transaction: none! Important;"
Marwen Trabelsi
15
Observe que esta resposta está errada porque ELE DESATIVA TODAS AS ANIMAÇÕES, não apenas aquelas que são manipuladas pelo Angular.
empilhamento de
1
Tentaste? deixe-me ver uma amostra do seu código. Funciona para mim e para mais de seis pessoas que o aprovaram
David Addoteye
2
Eu adicionei uma .no-animate, .no-animate-children *regra para cobrir crianças, etc
Kimball Robinson
1
@DavidAddoteye esta solução não é viável se você tiver um ng-show ou ng-if sobre um elemento com transição .. Quer dizer .. se eu tiver um carregador giratório que aparece apenas durante a solicitação de http e desaparece quando a solicitação é resolvida, adicionando esta classe não resultará em nenhuma animação !, a resposta de Michael é ok, mas muito tediosa de implementar, e você deve tentar evitar seletores de css nos controladores. Criar uma diretiva está OK, mas olhando para a resposta de Blowsie você descobrirá que a equipe AngularJS já forneceu uma maneira flexível de cuidar desse problema;)
edrian
106

Se você deseja habilitar animações para elementos específicos (ao invés de desabilitá-los para elementos específicos), você pode usar o $ animateProvider para configurar elementos com um nome de classe particular (ou regex) para animar.

O código a seguir habilitará animações para elementos que possuem a angular-animateclasse:

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

Aqui está um exemplo de marcação que inclui a angular-animateclasse para habilitar animações:

<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>

Exemplo do Plunker emprestado e modificado deste blog onde apenas o primeiro filtro tem animações (devido a ter a angular-animateclasse).

Observe que estou usando angular-animatecomo exemplo e é totalmente configurável usando a .classNameFilterfunção.

Gloopy
fonte
5
Você salvou meu dia. Muito obrigado
gustavohenke 08/08/2014
Esta é a solução mais elegante, pois requer ativação para animações e os elementos animados são claramente diferenciados de outros pelo nome da classe.
Nikola M.
2
Esta deve ser a solução aceita. Funciona perfeito e salvou meu dia!
9
use /^(?:(?!ng-animate-disabled).)*$/regex para desativar animação com ng-animate-disabledclasse.
IcanDivideBy0
Ótima solução! Eu tenho uma tabela paginada com 20 linhas por página. Um terço do tempo para alternar as páginas era consumido pelo navegador processando as classes css de animação que nem estavam sendo usadas.
Kevin
81

Existem duas maneiras de distribuir animações em AngularJS se você tiver o módulo ngAnimate como uma dependência do seu módulo:

  1. Desative ou ative a animação globalmente no serviço $ animate:

    $animate.enabled(false);
  2. Desabilite as animações para um elemento específico - este deve ser o elemento para que angular adicionará as classes css de animationstate (por exemplo, ng-enter, ...)!

    $animate.enabled(false, theElement);

Na versão Angular 1.4, você deve inverter os argumentos:

$animate.enabled(theElement, false);

Documentação para$animate .

Michael
fonte
2
Isso não funciona em elementos específicos conforme o esperado. Se eu desligar as animações globalmente e depois habilitá-las em um elemento específico, não funciona.
Kushagra Gour
1
Essa resposta deve ser removida ou editada para especificar em qual versão do Angular ela realmente funciona. Para 1.2.10, definitivamente não funciona para habilitar seletivamente a animação para certos elementos, que é o ponto principal da questão AFAICT.
Trindaz,
Alguém sabe se a opção 2 está funcionando na versão 1.2.25?
khorvat
1
Apenas olhando a documentação ( docs.angularjs.org/api/ng/service/$animate ) parece que o «elemento» é o primeiro parâmetro a ser passado para a função habilitada.
DanielM
49

Para desativar o ng-animate para certos elementos, usando uma classe CSS, que segue o paradigma Angular animate, você pode configurar o ng-animate para testar a classe usando regex.

Config

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

Uso

Simplesmente adicione a ng-animate-disabledclasse a qualquer elemento que deseja ignorar pelo ng-animate.


Crédito http://davidchin.me/blog/disable-nganimate-for-selected-elements/

Blowsie
fonte
7
Acho que essa é a maneira mais correta de filtrar o comportamento do organimo!
edrian
6
Valeu a pena procurar por esta resposta.
Jossef Harush
Posso confirmar que, com a versão mais recente do AngularJS, esta é definitivamente a melhor solução para o problema.
Adam Reis
44

obrigado, escrevi uma diretiva que você pode colocar no elemento

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
fonte
Esta é uma abordagem muito bacana, nem sempre é claro como acessar o objeto de elemento, e com algumas das outras abordagens, tenho medo de bagunçar meus controladores com Javascript referenciando um ou vários elementos definidos em um template . Parece uma grande separação de preocupações, parabéns!
Mattygabe
2
A ordem dos parâmetros é invertida em $ animate.enabled, se alguém estiver se perguntando por que isso desativa toda a animação ng. Funciona perfeitamente se você usar$animate.enabled(element,false);
gss
Desculpas, vejo que só se aplica a 1.4.x +, o código acima está correto para as versões anteriores.
gss
19

Descobri que $animate.enabled(false, $element);funcionará para elementos que usam ng-showou, ng-hidemas não funcionará para elementos que usam ng-ifpor algum motivo! A solução que acabei usando foi apenas fazer tudo em CSS, o que aprendi neste tópico no GitHub .

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
fonte
Meu caso era que, com o ngAnimate carregado, uma classe como .loading.ng-hide ficaria na tela até que um loop de animação completo fosse concluído. Esta é a resposta mais limpa, porque basicamente é apenas alimentar a configuração certa para o ngAnimate e usá-la normalmente. Isso é preferível a configurá-lo incorretamente e, em seguida, desativá-lo. Então, +1 para você, gostaria de poder dar mais para igualar a pontuação aqui.
Eric,
Esta é a resposta mais complicada. Fazer isso com css é mais melhor do que mexer com js.
manas,
Por favor, olhe a resposta de @Blowsie, essa é a maneira mais genérica e correta de lidar com isso
edrian
3

Eu NÃO quero usar o ngAnimate no meu ng-if, então esta seria a minha solução:

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

Apenas postando isso como mais uma sugestão!

Betty St
fonte
2

Eu tenho uma lista da qual o primeiro liestá oculto usando ng-hide="$first". Usando ng-enterresulta em liser mostrado por meio segundo antes de desaparecer.

Com base na solução de Chris Barr, meu código agora se parece com este:

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
fonte
0

Eu sei que é uma resposta atrasada, mas aqui usamos no MainController:

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

Mas o problema é que quando desabilitamos todas as animações, o ui-select é configurado para opacity: 0.

Portanto, é necessário definir a opacidade para 1 usando CSS:

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

Isso definirá a opacidade corretamente e o ui-select funcionará.

David Branco
fonte