Schieben Sie den Effekt mit ng-show und ng-animate nach oben / unten

74

Ich versuche ng-animate, ein ähnliches Verhalten wie bei JQuery slideUp()und zu erzielen slideDown(). Nur ich würde lieber verwendenng-show

Ich schaue mir das ng-animate-Tutorial hier an - http://www.yearofmoo.com/2013/04/animation-in-angularjs.html ,

und ich kann den Ein- / Ausblendeffekt in dem bereitgestellten Beispiel reproduzieren.

Wie kann ich das CSS ändern, um ein Auf- / Ab-Verhalten zu erzielen? Wenn möglich, ist es auch besser, wenn das CSS die Komponentenhöhe in Pixel nicht kennt. Auf diese Weise kann ich das CSS für verschiedene Elemente wiederverwenden.

Tony Lâmpada
quelle
1
Ich glaube nicht, dass Sie ng-show dazu bringen können, Animationen zu verarbeiten. Das ist nicht die beabsichtigte Verwendung. Dafür ist ng-animate da. Warum möchten Sie ng-show speziell verwenden?
Jonathan Palumbo
1
Danke Jonathan. Ich denke du liegst falsch. Das angegebene Beispiel macht genau das: eine Kombination aus ng-show und ng-animate (suchen Sie nach "Animating ngShow & ngHide"). Wie auch immer, ich möchte einfach einen Effekt, um ein Div zu zeigen / zu verbergen, das auf und ab rutscht.
Tony Lâmpada
Mein Fehler, ich habe ng-animate nicht benutzt. Es sieht so aus, als ob sie zusammenarbeiten.
Jonathan Palumbo
Sie können versuchen, das line-heightCSS-Attribut von 0 bis 100% zu verwenden. Manchmal funktioniert es ... Poste deine Geige, als wir dir besser helfen können. Wenn Sie einen guten Weg finden, senden Sie mir bitte dieses Beispiel, um es auf meiner Website zu platzieren: AngularJS Ng-Animate
Bruno Croys Felthes
Überprüfen Sie dies aus nganimate.org
Alex Figueiredo

Antworten:

87

Ich habe eine Angular-Direktive geschrieben, die slideToggle()auf jQuery verzichtet.

https://github.com/EricWVGG/AngularSlideables

Eric_WVGG
quelle
1
Das sieht genau so aus, wie ich es wollte. Vielen Dank!
Tony Lâmpada
3
@BastienSander Angular bietet eine Teilmenge einiger Methoden von Jquery, wenn Sie jquery nicht einschließen, bevor Sie Angular einschließen. API-Dokumente hierfür: docs.angularjs.org/api/ng/function/angular.element .css und .bind are dort bereitgestellt (wird für die Variable "Element" verwendet). Die Eigenschaften "Beschleunigung" und "Dauer" werden nicht für Elemente verwendet, daher verweisen sie nicht auf die gleichnamigen Jquery-Methoden, sondern auf Eigenschaften, die an die HTML-Attribute (attrs-Objekt) übergeben werden.
Jay Klehr
2
Der minimalste Slider im "Akkordeon" -Stil, den ich je gesehen habe! Vielen Dank! Wir haben es ein wenig modifiziert, um IDs und Klassenmaterial zu entfernen, das wir als unnötig angesehen haben, da wir die Elemente ohne IDs finden konnten: plnkr.co/edit/11NIZqB3G3KYKI0OChGA?p=preview
Pylinux
1
Die IDs werden irgendwie benötigt (wenn Sie ein Element ablegen möchten, das sich woanders befindet), also habe ich eine geringfügige Änderung vorgenommen, um einige Fehler zu beheben, und jetzt funktioniert es wie ein Zauber. plnkr.co/edit/XdRjap3TPFEC9180yq9k?p=preview
Marcio
7
Ich weiß, dass wir dies zu Tode gebracht haben, aber ich mag es, die Sichtbarkeit an Variablen zu binden. Diese Lösung erlaubt auch keine eingebetteten Schieberegler. Ich habe eine Geige erstellt, die beides kann: jsfiddle.net/rh7z7w0a/2
jbodily
40

Das ist eigentlich ziemlich einfach. Alles was Sie tun müssen, ist das CSS zu ändern.

Hier ist eine Geige mit einer sehr einfachen Überblendanimation: http://jsfiddle.net/elthrasher/sNpjH/

Um daraus eine gleitende Animation zu machen, musste ich zuerst mein Element in eine Box legen (das ist der Foliencontainer), dann ein weiteres Element hinzufügen, um das verlassene zu ersetzen, nur weil ich dachte, es würde schön aussehen. Nehmen Sie es heraus und das Beispiel wird immer noch funktionieren.

Ich habe das Animations-CSS von "Überblenden" in "Folie" geändert, aber bitte beachten Sie, dass dies die Namen sind, die ich ihm gegeben habe. Ich hätte eine Folienanimation mit dem Namen "Fade" oder irgendetwas anderes schreiben können.

Der wichtige Teil ist, was in der CSS ist. Hier ist das Original-Fade-CSS:

.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;
}

Dieser Code ändert die Deckkraft des Elements von 0 (vollständig transparent) auf 1 (vollständig undurchsichtig) und wieder zurück. Die Lösung besteht darin, die Deckkraft in Ruhe zu lassen und stattdessen die Oberseite zu ändern (oder nach links, wenn Sie sich von links nach rechts bewegen möchten).

.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;
}

Ich wechsle auch von der relativen zur absoluten Positionierung, sodass jeweils nur eines der Elemente Platz im Container einnimmt.

Hier ist das fertige Produkt: http://jsfiddle.net/elthrasher/Uz2Dk/ . Hoffe das hilft!

elthrasher
quelle
Das war sehr hilfreich. Ich versuche herauszufinden, warum der 'Versteck'-Übergang in Ihrer Geige so plötzlich ist, @elthrasher
ericpeters0n
1
@ ericpeters0n - das liegt an den 0,5s am Ende der Übergangslinie. Das ist die Zeit, die benötigt wird, in diesem Fall eine halbe Sekunde. Sie können das beliebig einstellen. Versuchen Sie 5s oder 10s.
elthrasher
2
Das Verhalten ist irgendwie seltsam. Manchmal erscheint der Text von oben und manchmal von unten.
Nikk Wong
Ich weiß, dass es eine alte Antwort ist, aber wenn jemand dies versuchen möchte, möchte ich klarstellen, dass die Verwendung ng-hide="hidden == false"redundant ist. Wenn die hiddenVariable bereits ein Boolescher Wert ist, wird der Operator überhaupt nicht benötigt.
GMaiolo
17

Update für Angular 1.2+ (v1.2.6 zum Zeitpunkt dieses Beitrags):

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

Amit Portnoy
quelle
16
Animieren Sie die Spitzenposition nicht mit CSS, es ist sehr langsam und beansprucht viel Speicher. Verwenden Sie stattdessen übersetzen.
Michael Tempest
1
Funktioniert auch mit Angular 1.4. Getestet und es funktioniert wie ein Zauber!
Flame_Phoenix
16

Dies kann tatsächlich in CSS und sehr minimalem JS erfolgen, indem einfach eine CSS-Klasse (setzen Sie Stile nicht direkt in JS!) Mit z ng-click. B. einem Ereignis hinzugefügt wird . Das Prinzip ist, dass man nicht animieren kann height: 0;, height: auto;aber dies kann durch Animieren der max-heightEigenschaft ausgetrickst werden . Der Container wird beim .foo-openEinstellen auf den Wert "Automatische Höhe" erweitert - keine feste Höhe oder Positionierung erforderlich.

.foo {
    max-height: 0;
}

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

sehen Sie diese Geige von der ausgezeichneten Lea Verou

Beachten Sie in den Kommentaren, dass diese Animation zwar perfekt mit linearer Beschleunigung funktioniert, jede exponentielle Beschleunigung jedoch ein anderes Verhalten hervorruft als erwartet - aufgrund der Tatsache, dass die animierte Eigenschaft selbst ist max-heightund nicht heightselbst; Insbesondere wird nur der heightBruchteil der Lockerungskurve von max-heightangezeigt.

Luca
quelle
3
Das ist schlecht, weil sich die Animationsgeschwindigkeit je nach ändert max-height.
RushPL
warum ist es schlecht ? Wenn Sie Probleme mit der Animationsgeschwindigkeit haben, stellen Sie einfach die Übergangsdauer auf einen angemessenen Wert ein, der auf Ihrem Wert basiert max-height. Genau so sollen Übergänge funktionieren. Diese Methode hat tatsächlich den Vorteil, dass die Auf- / Ab-Geschwindigkeit unabhängig von derheight
Luca
1
@RushPL das ist eine faire Erklärung - es macht jetzt Sinn.
Luca
1
Ich muss über diesen Ansatz abstimmen. Einfach und mit dem ngAnimate-Framework.
Windmaomao
1
Dies sollte als Antwort markiert werden, da ich hier auf der Suche nach einem Weg zum Betrügen der Höhe geführt wurde: Auto wie das Originalplakat war
Erik Grosskurth
8

Am Ende habe ich den Code für meine andere Antwort auf diese Frage aufgegeben und stattdessen diese Antwort gewählt.

Ich glaube , der beste Weg , dies zu tun , ist nicht zu verwenden , ng-showund ng-animateüberhaupt.

/* 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);
                }
            });
        }
    }
});
dampfbetrieben
quelle
Vielen Dank für die Bereitstellung der neueren Lösung. Aus Neugier (da ich keine besonderen Probleme beim Huckepack von ng-hide / ng-show gefunden habe) ... was war das Problem bei diesem Ansatz?
Zai Chang
Sie sollten Ihre vorherige Antwort geändert haben, anstatt eine neue zu erstellen (stellen Sie sich das Chaos vor, wenn jeder jedes Mal eine neue Antwort erstellt, wenn er etwas ändern möchte ...)
tanguy_k
2
@tanguy_k Ich denke, es gibt eine Möglichkeit, die erste Antwort zu korrigieren, und möglicherweise sind beide Ansätze gültig. Ich hatte gehofft, jemand würde meine erste Antwort kritisieren und mir sagen, warum sie gelegentlich fehlschlägt. Ich denke, es kann mehrere gleich gute Antworten auf diese Frage geben.
Steampowered
1
Das Problem beim Bearbeiten der ursprünglichen Antwort ist, dass wenn der Fragesteller dies als "richtig" markiert und Sie dann signifikante Modifikationen vornehmen ... das scheint auch eine schlechte Idee zu sein.
Brett Green
6

Diese klassenbasierte Javascript-Animation funktioniert in AngularJS 1.2 (und 1.4 getestet)

Bearbeiten : Am Ende habe ich diesen Code aufgegeben und bin eine ganz andere Richtung gegangen. Ich mag meine andere Antwort viel besser . Diese Antwort gibt Ihnen in bestimmten Situationen einige Probleme.

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();}
    }
}

});

Fügen Sie einfach die .ng-hide-toggle-slidedownKlasse zum Containerelement hinzu, und das jQuery-Folienverhalten wird basierend auf der ng-hide-Klasse implementiert.

Sie müssen die $(element).css({display:'none'})Zeile in die beforeRemoveClassMethode aufnehmen, da jQuery kein slideDown ausführt, es sei denn, das Element befindet sich display: nonevor dem Starten der jQuery-Animation in einem Zustand von . AngularJS verwendet das CSS

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

um das Element auszublenden. jQuery ist dieser Status nicht bekannt, und jQuery benötigt die display:noneAnimation vor dem ersten Herunterrutschen.

Die AngularJS-Animation fügt die Klassen .ng-hide-animateund hinzu .ng-animate, während die Animation ausgeführt wird.

dampfbetrieben
quelle
Dies funktioniert perfekt für mich, während ich nicht in der Lage war, die anderen Antworten für mich gut zu bekommen. Up-Voted!
Zai Chang
@zaichang Am Ende habe ich diesen Code aufgegeben und bin eine ganz andere Richtung gegangen. Ich mag meine andere Antwort viel besser . Diese Antwort gibt Ihnen in bestimmten Situationen einige Probleme.
Steampowered
@steampowered Dies wird / kann nicht funktionieren ngIf. Aber ich sehe auch, dass es manchmal nicht funktioniert, selbst wenn Sie es verwenden ngShow. ZB scheint es nicht zu funktionieren, wenn ich es in einem mit UI-Bootstrap erstellten Modal verwende. Das ist komisch. Wann ist es für Sie gescheitert?
NoOne
die Anzeige: Nichts hat den Trick getan ... mit ng-animate / ng-show mit Enter / Leave-Funktionen und jquery UI-Umschalteffekten. Nichts hat richtig funktioniert, bis ich Anzeige hinzugefügt habe: keine zum Element ... danke!
Brett Green
3

Sie sollten dafür Javascript-Animationen verwenden - dies ist in reinem CSS nicht möglich, da Sie die Höhe eines Elements nicht kennen. Befolgen Sie die Anweisungen zur Implementierung von Javascript-Animationen und kopieren Sie slideUp und slideDown aus der Quelle von jQuery.

Andrew Joslin
quelle
0

Was ist los mit tatsächlich verwenden ng-animatefür , ng-showwie Sie erwähnt haben ?

<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>
phil294
quelle
1
Es funktioniert, wenn Sie die Höhe in Ihrem CSS fest codieren können, dies ist jedoch häufig nicht möglich.
Waruyama