Просуньте ефект вгору / вниз за допомогою 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.