Эффект скольжения вверх / вниз с помощью ng-show и анимации

72

Я пытаюсь использовать 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 для разных элементов.

  • 1
    Я не думаю, что вы сможете получить нг-шоу для обработки анимации. Это не его предполагаемое использование. Вот для чего нг-анимация. Почему вы хотите использовать ng-show специально?
  • 1
    Спасибо Джонатан. Я думаю, что вы ошибаетесь. Данный пример делает именно это: комбинация ng-show и ng-animate (ищите «Animating ngShow & ngHide»). В любом случае, то, что я хочу, это просто эффект, чтобы показать / скрыть div, скользящий вверх и вниз.
Показать ещё 3 комментария
Теги:

8 ответов

78
Лучший ответ

Я написал директиву Angular, которая делает slideToggle() без jQuery.

https://github.com/EricWVGG/AngularSlideables

  • 1
    Это выглядит так же, как я хотел. Спасибо!
  • 0
    Большое спасибо, похоже на отличную директиву
Показать ещё 7 комментариев
38

Это на самом деле довольно легко сделать. Все, что вам нужно сделать, это изменить 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/. Надеюсь, это поможет!

  • 0
    Это было очень полезно. Я пытаюсь выяснить, почему переход «скрыть» так внезапно в вашей скрипке, @elthrasher
  • 1
    @ ericpeters0n - это из-за того, что 0,5 с в конце строки перехода. Это время, которое в этом случае займет полсекунды. Вы можете установить это на то, что вам нравится. Попробуйте 5 или 10 с.
Показать ещё 2 комментария
15

Это действительно можно сделать в 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.

  • 3
    Это плохо, потому что скорость анимации меняется в зависимости от max-height .
  • 0
    почему это плохо ? Если у вас есть проблемы со скоростью анимации, просто установите длительность перехода на разумное значение, основанное на вашей max-height . Именно так должны работать переходы. Этот метод на самом деле имеет то преимущество, что скорость скольжения / опускания остается постоянной независимо от height
Показать ещё 10 комментариев
15

обновить для 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)

  • 16
    Не анимируйте верхнюю позицию с помощью css, она очень медленная и занимает много памяти. Вместо этого используйте перевод.
  • 1
    Также работает на Angular 1.4. Протестировано и работает как шарм!
7

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

Я считаю, что лучший способ сделать это - не использовать 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);
                }
            });
        }
    }
});
  • 0
    Спасибо за предоставление более нового решения. Из любопытства (поскольку я не обнаружил каких-либо особых проблем с переключением с ng-hide / ng-show) ... в чем была проблема с этим подходом?
  • 0
    Вы должны были изменить свой предыдущий ответ вместо того, чтобы создавать новый (представьте себе беспорядок, если все создают новый ответ каждый раз, когда хотят что-то изменить ...)
Показать ещё 2 комментария
5

Эта анимация 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 во время анимации.

  • 0
    Это прекрасно работает для меня, пока я не смог заставить другие ответы работать хорошо для меня. Up-голосовали!
  • 0
    @zaichang Я отказался от этого кода и пошел в совершенно другом направлении. Мне больше нравится мой другой ответ . Этот ответ даст вам некоторые проблемы в определенных ситуациях.
Показать ещё 2 комментария
4

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

0

Что случилось с использованием 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>
  • 1
    Это работает, если вы можете жестко кодировать высоту в своем CSS, но это часто невозможно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню