【问题标题】:Animate dynamic height with AngularJS使用 AngularJS 动画动态高度
【发布时间】:2015-06-24 12:11:47
【问题描述】:

所以,我一直在尝试制作类似于 Angular Accordion 的动画,但没有成功。我用固定的高度计算出来,但不是动态的。高度:自动;不起作用。 :(

也许你们中的一些人有类似的问题?

我的代码:

html:

  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-route.js"></script>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>

  <body>
    <section ng-app="myApp">
    <div ng-controller="myCtrl as vm">
        <ul ng-init="vm.tab=1">
            <li ng-repeat="item in vm.data">
              <a href ng-click="vm.tab = item.thingy">{{item.name}}</a>
              <div ng-show="vm.tab === item.thingy">
                <img ng-src="{{item.img}}" width="50px"><br>
                <div class="longDiv">{{item.description}}</div>
              </div>
            </li>
        </ul>
    </div>
  </section>
</body>
</html>

js:

var app = angular.module('myApp', []);

app.controller('myCtrl', ['$scope',
  function($scope) {
    var vm = this;

    vm.data = [{
      name: "First",
      title: "oneTitle",
      description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur.",
      year: "2013",
      img: "http://static.hdw.eweb4.com/media/wp_400/1/5/42735.jpg",
      thingy: 1
    }, {
      name: "third",
      title: "twoTitle",
      description: "Quisque pulvinar libero sed eros ornare",
      year: "2014",
      img: "http://static.hdw.eweb4.com/media/wp_400/1/1/8519.jpg",
      thingy: 2
    }, {
      name: "Second",
      title: "threeTitle",
      description: "Cras accumsan ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur massa vitae tortor vehicula .",
      year: "2015",
      img: "http://static.hdw.eweb4.com/media/wp_400/1/5/43326.jpg",
      thingy: 3
    }, {
      name: "fourth",
      title: "FourTitle",
      description: "Suspendisse ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur ipsum dolor sit amet, consectetur vitae mattis magna.",
      year: "2011",
      img: "http://static.hdw.eweb4.com/media/wp_400/1/5/42413.jpg",
  thingy: 4
    }];

  }
]);

提前致谢! plnkrhere

【问题讨论】:

  • 您可以为此使用 UI Bootstrap,它是用纯 AngularJs 编写的引导组件,因此您可以轻松自定义。检查angular-ui.github.io/bootstrap,第一个组件是手风琴。
  • 小澄清:您是否要求将所有可折叠面板设置为相同的高度?
  • 不,我希望面板向下滑动以显示内容。仅设置宽度,高度可能会改变。
  • 点击时向下滑动和向上滑动?
  • 是的,基本上将活动元素的高度从 0 设置为 auto。

标签: css angularjs jquery-animate accordion


【解决方案1】:

我通过创建“折叠”指令解决了这个问题:

ngModule.directive('collapse', [function () {
    return {
        restrict: 'A',

        link: function ($scope, ngElement, attributes) {
            var element = ngElement[0];

            $scope.$watch(attributes.collapse, function (collapse) {
                var newHeight = collapse ? 0 : getElementAutoHeight();

                element.style.height = newHeight +"px";
                ngElement.toggleClass('collapsed', collapse);
            });

            function getElementAutoHeight() {
                var currentHeight = getElementCurrentHeight();

                element.style.height = 'auto';
                var autoHeight = getElementCurrentHeight();

                element.style.height = currentHeight +"px";
                getElementCurrentHeight(); // Force the browser to recalc height after moving it back to normal

                return autoHeight;
            }

            function getElementCurrentHeight() {
                return element.offsetHeight
            }
        }
    };
}]);

要使用该指令,您只需将其放在元素上并将其设置为表示是否折叠它的范围变量:

<div collapse="isCollapsed">
    This will be collapsed
</div>

现在您只需要在高度上应用 CSS 过渡,它就会平滑地折叠和展开。 由于该指令还添加了一个类,因此您可以应用其他转换,例如不透明度。

这是一个带有示例的 Codepen:http://codepen.io/KaidenR/pen/GoRJLx

【讨论】:

    【解决方案2】:

    修改@kaiden 答案,如果使用角度指令可以使用

    require('./').directive('collapse', collapseDirective);
    
    /**
    * @ngInject
    */
    function collapseDirective() {
    
       return {
        restrict: 'A',
        link: link
       };
    
       function link($scope, ngElement, attributes) {
         var element = ngElement[0];
    
         // set the height as a data attr so we can use it again later
         element.dataset.heightOld = angular.element(element).prop('offsetHeight');
    
         $scope.$watch(attributes.collapse, function (collapse) {
           var newHeight = !collapse ? 0 : element.dataset.heightOld;
           element.style.height = newHeight + 'px';
           ngElement.toggleClass('collapsed', collapse);
         }); 
       }
     }
    

    作为链接功能,只需为高度添加 CSS 过渡。这会设置一个数据属性来存储高度,然后在切换时使用它。在我的应用程序中,我使用了一些标记,例如

    <ion-item class="item-accordion" collapse="vm.isActive($index)">
    

    请注意,这是在 ng-repeat 中并调用视图模型上的函数。这也是一个离子项目,因此是离子项目标签。

    【讨论】:

      【解决方案3】:

      您可以尝试将 max-height 设置为 0,然后按照此处的建议删除样式/类:

      http://css3.bradshawenterprises.com/animating_height/

      【讨论】:

      • 谢谢,但是悬停对我不起作用。我需要它在点击时显示,就像在我的示例中一样:(
      【解决方案4】:

      所以,经过长时间的努力,我想出了一种最简单、最快捷的方法来制作带有 Angular 内容的 jQuery 手风琴,我想出了一种简单但混乱的方法。

      基本上我在我的 $scope-accordion 中创建了一个新变量,并将所有手风琴 html 放入其中:

      vm.data = [{
        name     : "First",
        accordion: ["<h3>Title1</h3><div>Content 1</div><h3>Title2</h3><div>Content 1</div>"]};
      

      对我来说这是可行的,因为现在我可以在 ng-repeat 中使用这个变量:

      <div ng-repeat="item in vm.data>
          <div ng-repeat="acc in item.accordion" ng-bind-html="acc | normalHtml"></div>
      

      只要这个变量中只有一个字符串,我就会得到一个手风琴 div。 之后我在 setTimout 函数中调用了手风琴函数,一切正常。

      但是这很混乱,有点像“用锤子,我可以用羽毛”的情况。

      所以,目前这对我来说很好,但我仍在寻找更漂亮的解决方案。

      感谢大家帮助我。如果你们中的一些人知道如何使它变得更好,我欢迎每一个答案:)

      【讨论】:

        【解决方案5】:

        好吧,我想我找到了圣杯。至少对于我的用途:)

        我在使用来自@Kaiden 和@Gareth Fuller 的解决方案的嵌套折叠元素时遇到了问题,因为任何外部折叠元素都会保持它在任何内部折叠元素折叠之前获得的原始高度。所以我从@Icycool 的建议中得到启发,改为在最大高度上设置动画,并将高度设置为“自动”,从而解决了这个问题。

        您可以在下面运行一个工作演示。

        var testModule = angular.module('testModule', []);
        
        testModule.controller('testController', function($scope) {
          $scope.isCollapsed = false;
        
          $scope.toggle = function() {
            $scope.isCollapsed = !$scope.isCollapsed;
          };
        });
        
        testModule.directive('collapse', [function() {
          return {
            restrict: 'A',
        
            link: function link($scope, $element, $attrs) {
              var element = $element[0];
              $element.addClass('collapse');
              const originalHeight = $element.prop('offsetHeight');
        
              $scope.$watch($attrs.collapse, function(collapse) {
                if (collapse) {
                  element.style.maxHeight = '0px';
                } else {
                  element.style.maxHeight = originalHeight + 'px';
                }
                $element.toggleClass('sh-collapsed', collapse);
              });
            }
          };
        }]);
        .collapse {
          height: 'auto';
          overflow: hidden;
          transition: max-height 0.3s;
          background: lightgreen;
        }
        <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
        <div ng-app="testModule" ng-controller="testController">
          <button type="button" ng-click="toggle()">Toggle</button> Collapsed: {{isCollapsed}}
          <ul collapse="isCollapsed">
            <li>Line One</li>
            <li>Line Two</li>
            <li>Line Three</li>
            <li>Line Four</li>
            <li>Line Five</li>
          </ul>
        </div>

        【讨论】:

          猜你喜欢
          • 2014-04-02
          • 1970-01-01
          • 2013-03-01
          • 2013-06-09
          • 2018-02-28
          • 1970-01-01
          • 2013-05-05
          • 2018-03-23
          • 1970-01-01
          相关资源
          最近更新 更多