Просуньте ефект вгору / вниз за допомогою ng-show та ng-animate


74

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

Я переглядаю підручник з ng-animate тут - http://www.yearofmoo.com/2013/04/animation-in-angularjs.html ,

і я можу відтворити ефект затухання / виходу у наведеному прикладі.

Як я можу змінити CSS, щоб отримати поведінку слайд вгору / вниз? Крім того, якщо це можливо, краще, щоб css не знав про висоту компонента в пікселях. Таким чином я можу повторно використовувати css для різних елементів.


1
Я не думаю, що ви зможете отримати ng-show для обробки анімації. Це не є призначенням. Саме для цього призначений ng-animate. Чому ви хочете використовувати саме ng-show?
Джонатан Палумбо,

1
Дякую Джонатану. Думаю, ви помиляєтесь. Наведений приклад робить саме це: поєднання ng-show та ng-animate (шукайте "Animating ngShow & ngHide"). У будь-якому випадку, те, що я хочу, - це просто ефект показати / приховати div, що ковзає вгору і вниз.
Тоні Лампада,

Моя помилка, я не використовував ng-animate. Виглядає так, ніби вони працюють спільно між собою.
Джонатан Палумбо,

Ви можете спробувати використовувати line-heightатрибут css, від 0 до 100%. Іноді це працює ... Опублікуйте свою скрипку, ніж ми можемо вам допомогти краще. Якщо ви знайдете хороший спосіб це зробити, надішліть мені його, щоб розмістити цей зразок на моєму сайті: AngularJS Ng-Animate
Bruno Croys Felthes

Перегляньте це на nganimate.org
Алекс Фігейредо

Відповіді:


87

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

https://github.com/EricWVGG/AngularSlideables


1
Це виглядає точно так, як я хотів. Дякую!
Тоні Лампада,

3
@BastienSander Angular надає підмножину деяких методів Jquery, якщо ви не включите jquery перед тим, як включити Angular, api docs для цього тут: docs.angularjs.org/api/ng/function/angular.element .css та .bind є надається там (що використовується для змінної "елемент"). Властивості полегшення та тривалості не використовуються для елемента, тому вони не посилаються на однойменні методи Jquery, а є властивостями, переданими в атрибутах HTML (об'єкт attrs).
Jay Klehr,

2
Найбільш мінімальний повзунок у стилі "акордеон", який я коли-небудь бачив! Дякую! Ми трохи змінили його, щоб видалити ідентифікатори та речі класу, які, на нашу думку, були непотрібними, оскільки ми могли знайти елементи без ідентифікаторів: plnkr.co/edit/11NIZqB3G3KYKI0OChGA?p=preview
Pylinux

1
Ідентифікатори потрібні (якщо ви хочете випасти елемент, який знаходиться десь в іншому місці), тому я зробив трохи модифікації, виправляючи деякі помилки, і тепер це працює як шарм. plnkr.co/edit/XdRjap3TPFEC9180yq9k?p=preview
Марсіо

7
Я знаю, що ми зіпсували це до смерті, але мені подобається прив'язувати видимість до змінних. Крім того, це рішення не дозволяє використовувати вбудовані повзунки. Я створив скрипку, яка робить і те, і інше: jsfiddle.net/rh7z7w0a/2
jbodily

40

Це насправді досить просто зробити. Все, що вам потрібно зробити, це змінити css.

Ось скрипка з дуже простою анімацією затухання: http://jsfiddle.net/elthrasher/sNpjH/

Щоб перетворити його на ковзну анімацію, мені спочатку довелося помістити свій елемент у вікно (це слайд-контейнер), потім я додав інший елемент, щоб замінити той, що залишався, лише тому, що я думав, що це буде виглядати гарно. Дістаньте, і приклад все одно буде працювати.

Я змінив css анімації з "зникати" на "слайд", але зауважте, що це я назвав. Я міг би написати слайд-анімацію css з назвою 'зникати' або щось інше з цього приводу.

Важливою є те, що в CSS. Ось оригінальний cade:

.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/ . Сподіваюся, це допомагає!


Це було дуже корисно. Я намагаюся зрозуміти, чому перехід "приховування" настільки раптовий у вашій скрипці, @elthrasher
ericpeters0n

1
@ ericpeters0n - це через те, що 0,5 с в кінці лінії переходу. Це стільки часу займе, у цьому випадку - пів секунди. Ви можете встановити це як завгодно. Спробуйте 5 або 10 секунд.
elthrasher

2
Поведінка якась дивна. Іноді текст з’являється зверху, а іноді знизу.
nikk wong

Я знаю, що це стара відповідь, але якщо хтось хоче спробувати, я хотів би пояснити, що використання ng-hide="hidden == false"є зайвим, якщо hiddenзмінна вже є логічною, тоді оператор взагалі не потрібен.
GMaiolo

17

оновлення для 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;
}

( плунжер )


16
Не анімуйте верхню позицію за допомогою css, вона дуже повільна і займає багато пам'яті. Замість цього використовуйте переклад.
Майкл Темпест

1
Також працює над Angular 1.4. Перевірено, і це працює як шарм!
Flame_Phoenix

16

Це насправді можна зробити в CSS і дуже мінімальному JS, просто додавши клас CSS (не встановлюйте стилі безпосередньо в JS!), Наприклад, ng-clickподією. Принцип полягає в тому, що один не може оживити height: 0;до , height: auto;але це може бути обдурять анімувати max-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.
RushPL

чому це погано ? Якщо у вас проблеми зі швидкістю анімації, просто встановіть тривалість переходу на розумне значення залежно від вашого max-height. Це саме те, як повинні працювати переходи. Цей метод насправді має ту перевагу, що швидкість ковзання / зниження залишається незмінною незалежно відheight
Лука

1
@RushPL це справедливе пояснення - це має сенс зараз.
Лука

1
Я повинен проголосувати за такий підхід. Простий, а також використання фреймворку ngAnimate.
windmaomao

1
Це повинно бути позначено відповіддю, оскільки мене привели сюди у пошуках способу обдурити висоту: авто, як оригінальний плакат
Ерік Гросскурт,

8

У підсумку я відмовився від коду для своєї іншої відповіді на це питання і замість цього пішов із цією відповіддю.

Я вважаю , що найкращий спосіб зробити це , щоб не використовувати 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);
                }
            });
        }
    }
});

Дякуємо за надання нового рішення. З цікавості (оскільки я не знайшов жодних особливих проблем із відключенням від ng-hide / ng-show) ... в чому проблема такого підходу?
zai chang

Вам слід було змінити свою попередню відповідь, замість того, щоб створювати нову (уявіть собі безлад, якщо кожен створює нову відповідь кожного разу, коли хоче щось змінити ...)
tanguy_k

2
@tanguy_k Я думаю, що може бути спосіб виправити першу відповідь, і, можливо, обидва підходи є дійсними. Думаю, я сподівався, що хтось критикуватиме мою першу відповідь і скаже мені, чому вона часом не вдається. Я думаю, що на це питання може бути кілька однаково хороших відповідей.
паровий привід

1
Проблема з редагуванням оригінальної відповіді полягає в тому, що якщо запитувач позначив це як "правильний", і тоді ви робите значні моди ... це теж здається поганою ідеєю.
Бретт Грін

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 не буде виконувати slideDown, якщо елемент не знаходиться в стані display: noneдо початку анімації jQuery. AngularJS використовує CSS

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

щоб приховати елемент. jQuery не знає цього стану, і jQuery потребуватиме display:noneперед першою анімацією слайда.

Анімація AngularJS додаватиме класи .ng-hide-animateі, .ng-animateпоки відбувається анімація.


Це ідеально підходить для мене, поки я не міг отримати інші відповіді, які б добре працювали для мене. Голосували!
zai chang

@zaichang Я в підсумку відмовився від цього коду і пішов зовсім в іншому напрямку. Інша моя відповідь мені подобається набагато більше . Ця відповідь дасть вам деякі проблеми в певних ситуаціях.
паровий привід

@steampowered З цим буде / не може працювати ngIf. Але я також бачу, що це іноді не працює, навіть коли ви використовуєте ngShow. Наприклад, здається, що це не працює, коли я використовую його в модалі, створеному за допомогою UI-Bootstrap. Це дивно. Коли це не вдалося для вас?
NoOne 02

дисплей: жодна річ не зробила трюк ... за допомогою ng-animate / ng-show з функціями enter / leave та перемиканням інтерфейсу jquery UI Nothign працював правильно, поки я не додав display: нічого до елемента ... дякую!
Brett Green

3

Для цього слід використовувати анімацію 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, але це часто неможливо.
Варуяма
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.