Angular.js: ng-if se comporta de maneira estranha com animações de quadro-chave infinito em CSS

Criado em 3 jan. 2014  ·  3Comentários  ·  Fonte: angular/angular.js

Relacionado a https://github.com/angular/angular.js/issues/4818

Veja o seguinte Plunker: http://plnkr.co/edit/i1DJ6ejtuHVFHty9jxfe?p=preview

O elemento <div class="box" ng-if="showBox"> tem uma animação infinita de 5 segundos para um fundo em ciclo permanente. Quando o valor de showBox é alternado, a animação do elemento começa novamente e não é removida do DOM até que os 5 segundos inteiros tenham se passado - apesar de nenhuma animação entrar / sair sendo definida.

Ainda mais problemático: se você alternar o valor várias vezes antes de a animação terminar (clique na caixa de seleção várias vezes), várias cópias do elemento serão exibidas simultaneamente.

ngAnimate moderate bug

Comentários muito úteis

O problema é que o ngAnimate pensa que sua animação infinita está lá para todos os eventos de animação usados ​​(como entrar, sair e assim por diante). E como é uma animação infinita, os eventos CSS nunca são disparados até que a contagem regressiva final tenha passado, que é após 7,5 segundos (5 x 1,5 == 7,5).

Você precisará dizer ao ng-animate para não animar a animação de fundo infinito, substituindo a classe CSS .ng-animate no elemento e cancelando as animações de quadro-chave.

http://plnkr.co/edit/fq7ZEO7tDnqLmavHoBfQ?p=preview

.box.ng-animate {
  -webkit-animation: none 0s;
  animation: none 0s;
}

Infelizmente, a detecção de estilos e classes CSS em JavaScript é altamente limitada. Com as versões anteriores do AngularJS, tínhamos a regra de que você só pode definir a animação / transição CSS na propriedade da animação (como .ng-enter, .ng-leave e assim por diante), mas isso causou mais problemas do que resolveu. Portanto, neste caso, você precisa fazer o oposto.

PS. Tudo que você precisa é o prefixo -webkit- e as propriedades animation padrão, já que todos os outros fornecedores abandonaram seus prefixos.

Todos 3 comentários

O problema é que o ngAnimate pensa que sua animação infinita está lá para todos os eventos de animação usados ​​(como entrar, sair e assim por diante). E como é uma animação infinita, os eventos CSS nunca são disparados até que a contagem regressiva final tenha passado, que é após 7,5 segundos (5 x 1,5 == 7,5).

Você precisará dizer ao ng-animate para não animar a animação de fundo infinito, substituindo a classe CSS .ng-animate no elemento e cancelando as animações de quadro-chave.

http://plnkr.co/edit/fq7ZEO7tDnqLmavHoBfQ?p=preview

.box.ng-animate {
  -webkit-animation: none 0s;
  animation: none 0s;
}

Infelizmente, a detecção de estilos e classes CSS em JavaScript é altamente limitada. Com as versões anteriores do AngularJS, tínhamos a regra de que você só pode definir a animação / transição CSS na propriedade da animação (como .ng-enter, .ng-leave e assim por diante), mas isso causou mais problemas do que resolveu. Portanto, neste caso, você precisa fazer o oposto.

PS. Tudo que você precisa é o prefixo -webkit- e as propriedades animation padrão, já que todos os outros fornecedores abandonaram seus prefixos.

Legal, obrigado pela solução alternativa.

A coisa de múltiplas cópias de uma só vez ainda parece um bug para mim: eu escrevo meu código pressupondo que um elemento usando ng-if está presente uma vez ou não está presente, e espero que o estrutura para evitar que se quebre tão facilmente devido a um erro inadvertido noob. Por favor, corrija-me se eu não entendi como ng-if (ou ng-switch ) deve funcionar.

As cópias múltiplas estavam lá porque as animações ainda estavam acontecendo. E $ animate tem uma animação catch-all para quadros-chave / transições que ocorre depois que sua duração * 1.5 expira. É por isso que eles desaparecem após um momento.

Seu código ng-if está correto. E sim, só existe quando é verdade. Mas os internos fazem uma nova cópia do elemento cada vez que a expressão se torna verdadeira novamente. Mas, como a animação está pendurada no elemento mais antigo, ela ainda não foi excluída até que todas as animações cheguem.

E ng-switch e ng-if operam da mesma maneira. Apenas o ng-switch possui vários elementos em vez de apenas um.

Esta página foi útil?
0 / 5 - 0 avaliações