Эффект затухания для вкладок в ui-bootstrap (Angular.JS)

Как добавить анимацию fade в tabset с помощью angular -ui-bootstrap?

Например, учитывая следующий код:

<tabset>
    <tab heading="Tab1">Some content</tab>
    <tab heading="Tab2">Other content</tab>
</tabset>

Я хочу, чтобы содержимое вкладок исчезало при переключении между ними. Я попытался добавить класс fade в теги tab (аналогично тому, как это сделать с файлом bootstrap3 js), но это не сработало.

Большое спасибо!

Ответы

Ответ 1

Так как tabset использует ng-class для управления вкладкой "active", что позволяет нам определить эффект затухания с анимацией angular, установив opacity = 0, когда "активный" класс удален/присоединен.

Сначала вам нужно загрузить модуль ngAnimate, включив angular-animate.js и настроить зависимость.

Добавьте в свой <head>:

<script src="https://code.angularjs.org/1.2.24/angular-animate.js"></script>

Задайте зависимость модуля:

angular.module("myApp", ["ui.bootstrap", "ngAnimate"]);

Теперь добавьте класс анимации в ваш таблеток.

<tabset class="tab-animation">
    <tab heading="Tab1">Some content</tab>
    <tab heading="Tab2">Other content</tab>
</tabset>

Поместите следующий код в ваш файл css:

/* set reference point */
.tab-animation > .tab-content {
    position: relative;
}

/* set animate effect */
.tab-animation > .tab-content > .tab-pane{
    transition: 0.2s linear opacity;
}

/* overwrite display: none and remove from document flow */
.tab-animation > .tab-content > .tab-pane.active-remove {
    position: absolute;
    top: 0;
    width: 100%;
    display: block;
}

/* opacity=0 when removing "active" class */
.tab-animation > .tab-content > .tab-pane.active-remove-active {
    opacity: 0;
}

/* opacity=0 when adding "active" class */
.tab-animation > .tab-content > .tab-pane.active-add {
    opacity: 0;
}

Это все. Вы можете проверить демонстрацию на Plunker.

Также посмотрите документ ngAnimate.

Ответ 2

Я закончил загрузку файла ui-bootstrap. Я все еще ноб с AngularJS, поэтому, пожалуйста, простите жаргон. Это нетрадиционный взлом, и его нужно реконфигурировать с помощью ng-animate, но он работает.

Откройте ui-bootstrap-tpls-0.10.0.js и найдите директиву "tab":

    .directive('tab', ['$parse', function($parse) {
    return {
    require: '^tabset',
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/tabs/tab.html',
    transclude: true,
    scope: {
    id:'@', // PATCH : GETTING TAB 'id' ATTRIBUTE
    heading: '@',
    onSelect: '&select', //This callback is called in contentHeadingTransclude
                      //once it inserts the tab content into the dom
    onDeselect: '&deselect'
    },
    // ...

Обратите внимание на дополнительный код для получения значения атрибута id (через переход, я думаю).



Несколько строк ниже, найдите:

     scope.$watch('active', function(active) {

и скопируйте его так:

          scope.$watch('active', function(active) {
      // Note this watcher also initializes and assigns scope.active to the
      // attrs.active expression.
      setActive(scope.$parent, active);

      if (active) {
        tabsetCtrl.select(scope);
        scope.onSelect();

        tab_id = attrs.id;
        $(".tab_pane_"+tab_id).hide(); // HIDE AT FIRST, SO IT CAN ACTUALLY FADE IN
        $(".tab_pane_"+tab_id).fadeIn(1000); // JQUERY TARGETING BY CLASS

      } else {
        scope.onDeselect();

        tab_id = attrs.id;
        $(".tab_pane_"+tab_id).hide(); // JQUERY TARGETING BY CLASS
      }

    });



Несколько строк ниже, найдите:

    scope.select = function() {

и добавьте внутрь:

    $(".tab-pane").hide();

поэтому все панели вкладок сначала спрятаются должным образом.



Затем найдите:

angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) { ...

и добавьте класс css в элемент tab-panel в соответствующем шаблоне, например:

angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/tabs/tabset.html",
"\n" +
"<div class=\"tabbable\">\n" +
"  <ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
"  <div class=\"tab-content\">\n" +
"    <div class=\"tab-pane tab_pane_{{tab.id}}\" \n" + // CLASS NAME IS DYNAMIC
"         ng-repeat=\"tab in tabs\" \n" +
"         ng-class=\"{active: tab.active}\"\n" + 
"         tab-content-transclude=\"tab\">\n" +
"    </div>\n" +
"  </div>\n" +
"</div>\n" +
"");
}]);





После изменения файла uj-bootstrap.js вы должны отредактировать свой шаблон представления (где вы извлекаете вкладки) и объявить атрибут id:

    <!-- TABS -->
    <tabset justified="true">
        <tab ng-repeat="tab in tabs" heading="{{tab.title}}" id="{{tab.id}}" >
            // ... TAB CONTENT



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


В случае, если вам интересно, как мои вкладки получили идентификаторы, ну, я ввел их в контроллер:

                        Tab1 = {
                        id:1,
                         'ShortDescription': ShortDescription, 
                         'FullDescription': FullDescription, 
                         'TabContent': TabContent1, 
                        title: "ProductTabTitleDefault1", 
                        // active:true
                    };

                    Tab2 = {
                        id:2,
                         'ShortDescription': ShortDescription, 
                         'FullDescription': FullDescription, 
                         'TabContent': TabContent1, 
                        title: "ProductTabTitleDefault2", 
                        // active:true
                    };


                    $rootScope.tabs = { 
                        'Tab1': Tab1, 
                        'Tab2': Tab2, 
                        };

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

Ответ 3

У меня есть альтернативное решение для хорошо написанного решения @user3413125. Он использует @keyframes для достижения перекрестного затухания, а не затухания, за которым следует постепенное исчезновение. См. демо на Plunker

Вот фрагментация CSS (постепенное уменьшение):

.tab-animation > .tab-content > .tab-pane.active-add {
    animation: 1s fade-in;
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

Технология ключевого кадра взята из Учебник AngularJs 14 - найдите "Анимация ключевого кадра CSS: анимация ngView", примерно на половину страницы.