简体   繁体   English

ui-bootstrap中选项卡的淡入淡出效果(Angular.JS)

[英]Fade effect for tabs in ui-bootstrap (Angular.JS)

How can I add fade animation to a tabset using angular-ui-bootstrap? 如何使用angular-ui-bootstrap将淡入淡出动画添加到tabset?

For example, given the following code: 例如,给出以下代码:

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

I would like the content of the tabs to fade when switching between them. 我希望标签的内容在它们之间切换时淡出。 I tried to add the fade class to the tab tags (similar to how you would do it with the bootstrap3 js file), but it didn't work. 我尝试将fade类添加到tab标签(类似于使用bootstrap3 js文件的方式),但它不起作用。

Many thanks! 非常感谢!

Since tabset use ng-class to control "active" tab, which allow us to define fade effect with angular animation by setting opacity=0 when "active" class is removed/attached. 由于tabset使用ng-class来控制“活动”选项卡,这允许我们通过在移除/附加“活动”类时设置opacity = 0来定义具有角度动画的淡入淡出效果。

First, you need to load ngAnimate module by including angular-animate.js and set up dependency. 首先,您需要通过包含angular-animate.js并设置依赖项来加载ngAnimate模块。

Add to your <head> : 添加到<head>

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

Set module dependency: 设置模块依赖:

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

Now add animation class to your tabset. 现在将动画类添加到tabset。

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

Put following code into your css file: 将以下代码放入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;
}

That's all. 就这样。 You can check the demo on Plunker . 您可以在Plunker上查看演示

Also take a look at ngAnimate doc . 另请查看ngAnimate doc

I ended up patching the ui-bootstrap file. 我最终修补了ui-bootstrap文件。 I'm still a noob with AngularJS, so please forgive the lingo. 我仍然是AngularJS的菜鸟,所以请原谅语言。 This is an unconventional hack, and needs to be refactored with ng-animate, but it works. 这是一个非传统的黑客攻击,需要用ng-animate重构,但它有效。

Open ui-bootstrap-tpls-0.10.0.js and look for the 'tab' directive : 打开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's content into the dom
    onDeselect: '&deselect'
    },
    // ...

Notice the extra code for retrieving the id attribute value (via transclusion, I guess). 注意用于检索id属性值的额外代码(通过翻译,我猜)。



A few lines below, look for : 下面几行,寻找:

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

and patch it like so : 并修补如下:

          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
      }

    });



A few lines below, look for : 下面几行,寻找:

    scope.select = function() {

and add inside : 并添加内部:

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

so all tab panes hide properly at first. 所以所有标签窗格首先都隐藏得很好。



Then, look for : 然后,寻找:

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

and add the css class to the tab-pane element in the corresponding template, like so : 并将css类添加到相应模板中的tab-pane元素,如下所示:

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" +
"");
}]);





Once the ui-bootstrap .js file is modified, you must edit your view template (where you fetch the tabs) and declare the 'id' attribute : 修改ui-bootstrap .js文件后,您必须编辑视图模板(获取选项卡的位置)并声明'id'属性:

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



You should get the basic concept, currently it's not very elegant (to put it mildly). 你应该得到基本的概念,目前它不是很优雅(温和地说)。 But it works. 但它的确有效。


In case you wonder how my tabs got id's, well, I injected them in my controller : 如果你想知道我的标签是如何得到id的,那么,我将它们注入我的控制器中:

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

Of course this is mockup data, but assuming your tabs and their content are dynamic, you can use a counter, and maybe use another key instead of "id" (but you'll have to change the rest accordingly). 当然这是模型数据,但假设您的标签及其内容是动态的,您可以使用计数器,也可以使用另一个键而不是“id”(但您必须相应地更改其余部分)。

I have an alternative solution to @user3413125's well-written solution above. 我有一个替代解决方案@ user3413125上面写得很好的解决方案。 It uses @keyframes to achieve a cross-fade, rather than a fade out followed by a fade in. See demo on Plunker 它使用@keyframes实现交叉渐变,而不是淡出然后淡入。请参阅Plunker上的演示

Here is the fade-in portion of the CSS (fade-out is similar): 这是CSS的淡入部分(淡出类似):

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

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

The keyframe technique is taken from the AngularJs tutorial 14 - look for "CSS Keyframe Animations: Animating ngView", about halfway down the page. 关键帧技术取自AngularJs教程14 - 寻找“CSS关键帧动画:动画ngView”,大约在页面的一半。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM