使用AngularJS为动态高度设置动画

时间:2015-06-24 12:11:47

标签: css angularjs jquery-animate accordion

所以,我一直在尝试像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
    }];

  }
]);

提前致谢! Plnkr here

5 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:3)

修改了@kaiden答案,如果使用angular指令可以使用

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过渡。这将设置一个data属性来存储高度,然后在切换时使用它。在我的应用程序中,我使用了一些标记,如

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

因此,经过长时间的努力,想出用角度内容制作jQuery手风琴的最简单和最简单的方法,我想出了一个简单而又凌乱的方式。

基本上我在我的$ scope-手风琴中制作了一个新变量,然后放入所有手风琴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函数中调用了accordion函数,一切正常。

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

所以,现在这对我来说没问题,但我仍在寻找更漂亮的解决方案。

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

答案 4 :(得分:0)

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

我在使用来自@Kaiden和@Gareth Fuller的解决方案时使用嵌套折叠元素时遇到了麻烦,因为任何外部折叠元素都会保留在任何内部折叠元素折叠之前所获得的原始高度。所以我从@ Icycool的建议中得到了启发,并改为在max-height上设置动画,并将高度设置为&#39; auto&#39;,这就解决了这个问题。

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

&#13;
&#13;
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);
      });
    }
  };
}]);
&#13;
.collapse {
  height: 'auto';
  overflow: hidden;
  transition: max-height 0.3s;
  background: lightgreen;
}
&#13;
<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>
&#13;
&#13;
&#13;