web-dev-qa-db-fra.com

Effet glisser vers le haut/bas avec ng-show et ng-animate

J'essaie d'utiliser ng-animate pour obtenir un comportement similaire à slideUp() et slideDown() de JQuery. Seulement je préférerais utiliser ng-show

Je regarde le tutoriel ng-animate ici - http://www.yearofmoo.com/2013/04/animation-in-angularjs.html ,

et je peux reproduire l'effet de fondu entrant/sortant dans l'exemple fourni.

Comment puis-je changer le fichier css pour obtenir un comportement de glissement vers le haut ou le bas? éléments.

73
Tony Lâmpada

J'ai écrit une directive angulaire qui slideToggle() sans jQuery.

https://github.com/EricWVGG/AngularSlideables

84
Eric_WVGG

C'est en fait assez facile à faire. Tout ce que vous avez à faire est de changer le fichier css.

Voici un violon avec une animation de fondu très simple: http://jsfiddle.net/elthrasher/sNpjH/

Pour en faire une animation glissante, je devais d’abord placer mon élément dans une boîte (c’est le conteneur de diapositives), puis j’ai ajouté un autre élément pour remplacer celui qui partait, simplement parce que je pensais que cela aurait l’air agréable. Enlevez-le et l'exemple fonctionnera toujours.

J'ai changé le css d'animation de 'fade' à 'slide' mais veuillez noter que ce sont les noms que je lui ai donnés. J'aurais pu écrire une css d'animation de diapositives nommée 'fade' ou n'importe quoi d'autre à ce sujet.

La partie importante est ce qui est dans le css. Voici le css original 'fade':

.fade-hide, .fade-show {
    -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
    -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
    -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
    transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
}
.fade-hide {
    opacity:1;
}
.fade-hide.fade-hide-active {
    opacity:0;
}
.fade-show {
    opacity:0;
}
.fade-show.fade-show-active {
    opacity:1;
}

Ce code modifie l'opacité de l'élément de 0 (complètement transparent) à 1 (complètement opaque) et inversement. La solution est de laisser l'opacité et de changer le sommet (ou la gauche si vous souhaitez vous déplacer de gauche à droite).

.slide-hide, .slide-show {
    -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
    -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
    -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
    transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
}
.slide-hide {
    position: relative;
    top: 0;
}
.slide-hide.slide-hide-active {
    position: absolute;
    top: -100px;
}
.slide-show {
    position: absolute;
    top: 100px;
}
.slide-show.slide-show-active {
    position: relative;
    top: 0px;
}

Je passe également du positionnement relatif au positionnement absolu, de sorte qu'un seul des éléments occupe de l'espace dans le conteneur à la fois.

Voici le produit fini: http://jsfiddle.net/elthrasher/Uz2Dk/ . J'espère que cela t'aides!

40
elthrasher

mise à jour pour Angular 1.2+ (v1.2.6 au moment de cet article):

.stuff-to-show {
  position: relative;
  height: 100px;
  -webkit-transition: top linear 1.5s;
  transition: top linear 1.5s;
  top: 0;
}
.stuff-to-show.ng-hide {
  top: -100px;
}
.stuff-to-show.ng-hide-add,
.stuff-to-show.ng-hide-remove {
  display: block!important;
}

( plunker )

17
Amit Portnoy

Cela peut réellement être fait en CSS et en JS très minimal en ajoutant simplement une classe CSS (ne définissez pas de styles directement dans JS!) Avec par exemple. un ng-clickevent. Le principe est qu'il est impossible d'animer height: 0; en height: auto;, mais cela peut être trompé en animant la propriété max-height. Le conteneur étendra sa valeur "auto-height" lorsque .foo-open est défini - aucun besoin de hauteur ou de positionnement fixes.

.foo {
    max-height: 0;
}

.foo--open {
    max-height: 1000px; /* some arbitrary big value */
    transition: ...
}

voir ce violon de l'excellente Lea Verou

En tant que préoccupation soulevée dans les commentaires, notez que, si cette animation fonctionne parfaitement avec l’assouplissement linéaire, tout assouplissement exponentiel produira un comportement différent de ce à quoi on pouvait s’attendre, car la propriété animée est max-height et non pas height. spécifiquement, seule la fraction height de la courbe d’assouplissement de max-height sera affichée.

15
Luca

J'ai fini par abandonner le code pour ma autre réponse à cette question et aller plutôt avec cette réponse.

Je crois que la meilleure façon de faire est de ne pas utiliser ng-show et ng-animate du tout.

/* Executes jQuery slideDown and slideUp based on value of toggle-slidedown 
   attribute.  Set duration using slidedown-duration attribute.  Add the 
   toggle-required attribute to all contained form controls which are
   input, select, or textarea.  Defaults to hidden (up) if not specified
   in slidedown-init attribute.  */
fboApp.directive('toggleSlidedown', function(){
    return {
        restrict: 'A',
        link: function (scope, elem, attrs, ctrl) {
            if ('down' == attrs.slidedownInit){
                elem.css('display', '');
            } else {
                elem.css('display', 'none');
            }
            scope.$watch(attrs.toggleSlidedown, function (val) {
                var duration = _.isUndefined(attrs.slidedownDuration) ? 150 : attrs.slidedownDuration;
                if (val) {
                    elem.slideDown(duration);
                } else {
                    elem.slideUp(duration);
                }
            });
        }
    }
});
7
steampowered

Cette animation javascript basée sur les classes fonctionne dans AngularJS 1.2 (et testé 1.4)

Edit: J'ai fini par abandonner ce code et je suis allé dans une direction complètement différente. J'aime mon autre réponse est beaucoup mieux }. Cette réponse vous donnera des problèmes dans certaines situations.

myApp.animation('.ng-show-toggle-slidedown', function(){
  return {
    beforeAddClass : function(element, className, done){
        if (className == 'ng-hide'){
            $(element).slideUp({duration: 400}, done);
        } else {done();}
    },
    beforeRemoveClass :  function(element, className, done){
        if (className == 'ng-hide'){
            $(element).css({display:'none'});
            $(element).slideDown({duration: 400}, done);
        } else {done();}
    }
}

});

Ajoutez simplement la classe .ng-hide-toggle-slidedown à l'élément conteneur et le comportement de glisser-déposer de jQuery sera implémenté en fonction de la classe ng-hide. 

Vous devez inclure la ligne $(element).css({display:'none'}) dans la méthode beforeRemoveClass car jQuery n'exécutera pas de slideDown sauf si l'élément est dans l'état display: none avant de lancer l'animation jQuery. AngularJS utilise le CSS 

.ng-hide:not(.ng-hide-animate) {
    display: none !important;
}

cacher l'élément. jQuery n'est pas au courant de cet état et jQuery aura besoin du display:none avant la première animation.

L'animation AngularJS ajoutera les classes .ng-hide-animate et .ng-animate pendant le déroulement de l'animation.

5
steampowered

Vous devez utiliser des animations Javascript pour cela - ce n'est pas possible en CSS pur, car vous ne pouvez connaître la hauteur d'aucun élément. Suivez les instructions qu'il a pour vous concernant la mise en œuvre de l'animation javascript et copiez slideUp et slideDown à partir de la source de jQuery.

4
Andrew Joslin

Qu'est-ce qui ne va pas avec l'utilisation de ng-animate pour ng-show comme vous l'avez mentionné?

<script src="lib/angulr.js"></script>
<script src="lib/angulr_animate.js"></script>
<script>
    var app=angular.module('ang_app', ['ngAnimate']);
    app.controller('ang_control01_main', function($scope) {

    });
</script>
<style>
    #myDiv {
        transition: .5s;
        background-color: lightblue;
        height: 100px;
    }
    #myDiv.ng-hide {
        height: 0;
    }
</style>
<body ng-app="ang_app" ng-controller="ang_control01_main">
    <input type="checkbox" ng-model="myCheck">
    <div id="myDiv" ng-show="myCheck"></div>
</body>
0
Blauhirn