Слайд вверх/вниз с помощью ng-show и ng-animate

Я пытаюсь использовать ng-animate, чтобы получить поведение, подобное JQuery slideUp() и slideDown(). Только я предпочел бы использовать ng-show

Я смотрю здесь учебник ng-animate - http://www.yearofmoo.com/2013/04/animation-in-angularjs.html,

и я могу воспроизвести эффект fade in/out в представленном примере.

Как я могу изменить css, чтобы получить слайд вверх/вниз? Кроме того, если возможно, лучше, чтобы css не знал о высоте компонента в пикселях. Таким образом, я могу повторно использовать CSS для разных элементов.

Ответ 2

Это на самом деле довольно легко сделать. Все, что вам нужно сделать, это изменить css.

Здесь сценарий с очень простой анимацией затухания: http://jsfiddle.net/elthrasher/sNpjH/

Чтобы превратить его в скользящую анимацию, мне сначала пришлось поместить свой элемент в поле (это контейнер слайдов), затем я добавил еще один элемент, чтобы заменить тот, который уходил, только потому, что я думал, что он будет выглядеть красиво, Возьмите его, и пример будет работать.

Я изменил анимацию css с "fade" на "slide", но обратите внимание, что это имена, которые я им дал. Я мог бы написать слайд-анимацию css с именем "fade" или что-нибудь еще в этом отношении.

Важная часть - это то, что в css. Здесь оригинал "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;
}

Этот код изменяет непрозрачность элемента от 0 (полностью прозрачный) до 1 (полностью непрозрачный) и обратно. Решение состоит в том, чтобы оставить непрозрачность в одиночку и вместо этого изменить верхнюю (или левую, если вы хотите переместить влево-вправо).

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

Я также перехожу от относительного к абсолютному позиционированию, поэтому только один из элементов занимает место в контейнере за раз.

Здесь готовый продукт: http://jsfiddle.net/elthrasher/Uz2Dk/. Надеюсь, это поможет!

Ответ 3

обновить для Angular 1.2 + (v1.2.6 на момент публикации):

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

Ответ 4

Это действительно можно сделать в CSS и очень минимальном JS, просто добавив класс CSS (не устанавливайте стили непосредственно в JS!), например. a ng-click. Принцип состоит в том, что нельзя окутать height: 0; в height: auto;, но это может быть обмануто анимированием свойства max-height. Контейнер будет расширяться до значения "auto-height", когда установлен .foo-open - нет необходимости в фиксированной высоте или позиционировании.

.foo {
    max-height: 0;
}

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

см. эту скрипку превосходной Ли Веро

В связи с замечанием, высказанным в комментариях, обратите внимание, что, хотя эта анимация отлично работает с линейным ослаблением, любое экспоненциальное ослабление приведет к поведению, отличному от того, что можно было ожидать - из-за того, что анимированное свойство max-height, а не height сам; в частности, будет отображаться только фракция height кривой ослабления max-height.

Ответ 5

В конце концов я отказался от кода для своего другого ответа на этот вопрос и пошел с этим ответом.

Я считаю, что лучший способ сделать это - не использовать ng-show и ng-animate вообще.

/* 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);
                }
            });
        }
    }
});

Ответ 6

Эта анимация javascript на основе классов работает в AngularJS 1.2 (и проверена 1.4)

Изменить. Я закончил тем, что отказался от этого кода и пошел совершенно в другом направлении. Мне нравится мой другой ответ намного лучше. Этот ответ даст вам некоторые проблемы в определенных ситуациях.

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

});

Просто добавьте класс .ng-hide-toggle-slidedown к элементу контейнера, а поведение слайда jQuery будет реализовано на основе класса ng-hide.

Вы должны указать строку $(element).css({display:'none'}) в методе beforeRemoveClass, потому что jQuery не будет выполнять slownDown, если элемент не находится в состоянии display: none до запуска анимации jQuery. AngularJS использует CSS

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

чтобы скрыть элемент. jQuery не знает об этом состоянии, а jQuery будет нуждаться в display:none до первой анимации спуска вниз.

Анимация AngularJS добавит классы .ng-hide-animate и .ng-animate во время анимации.

Ответ 7

Вы должны использовать анимацию Javascript для этого - это невозможно в чистом CSS, потому что вы не можете знать высоту любого элемента. Следуйте инструкциям, которые у вас есть о реализации анимации javascript, и скопируйте slideUp и slideDown из источника jQuery.

Ответ 8

Что случилось с использованием ng-animate для ng-show, как вы упомянули?

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