1

我正在构建一个带有嵌套评论列表的 Ionic 应用程序。我需要将回复动画化为子元素并保留状态。目前我正在使用带有 jQ​​uery slideToggle 的简单指令,但这不会保留状态(并且不是“Angular 方式”)。

Shlomi Assaf 的这个幻灯片动画示例是我需要的一个很好的开始,但它不处理嵌套元素。我创建他的 CodePen 项目的嵌套版本来演示这个问题。

我不确定是否应该修改动画函数以处理嵌套元素,或者我的控制器是否应该在子元素动画时(或完成后)调用祖先元素上的动画。

协助表示赞赏。这是使用原生 AngularJS 指令的 HTML 的基础:

<button ng-click="slideToggle1=!slideToggle1">Click Me</button>
<div class="slide-toggle" ng-show="slideToggle1"> ... </div>

这是原始动画功能:

app.animation('.slide-toggle', ['$animateCss', function($animateCss) {
    var lastId = 0;
    var _cache = {};

    function getId(el) {
      var id = el[0].getAttribute("data-slide-toggle");
      if (!id) {
        id = ++lastId;
        el[0].setAttribute("data-slide-toggle", id);
      }
      return id;
    }

    function getState(id) {
      var state = _cache[id];
      if (!state) {
        state = {};
        _cache[id] = state;
      }
      return state;
    }

    function generateRunner(closing, state, animator, element, doneFn) {
      return function() {
        state.animating = true;
        state.animator = animator;
        state.doneFn = doneFn;
        animator.start().finally(function() {
          if (closing && state.doneFn === doneFn) {
            element[0].style.height = '';
          }
          state.animating = false;
          state.animator = undefined;
          state.doneFn();
        });
      }
    }

    return {
      addClass: function(element, className, doneFn) {
        if (className == 'ng-hide') {
          var state = getState(getId(element));
          var height = (state.animating && state.height) ?
            state.height : element[0].offsetHeight;

          var animator = $animateCss(element, {
            from: {
              height: height + 'px',
              opacity: 1
            },
            to: {
              height: '0px',
              opacity: 0
            }
          });
          if (animator) {
            if (state.animating) {
              state.doneFn =
                generateRunner(true,
                  state,
                  animator,
                  element,
                  doneFn);
              return state.animator.end();
            } else {
              state.height = height;
              return generateRunner(true,
                state,
                animator,
                element,
                doneFn)();
            }
          }
        }
        doneFn();
      },
      removeClass: function(element, className, doneFn) {
        if (className == 'ng-hide') {
          var state = getState(getId(element));
          var height = (state.animating && state.height) ?
            state.height : element[0].offsetHeight;

          var animator = $animateCss(element, {
            from: {
              height: '0px',
              opacity: 0
            },
            to: {
              height: height + 'px',
              opacity: 1
            }
          });

          if (animator) {
            if (state.animating) {
              state.doneFn = generateRunner(false,
                state,
                animator,
                element,
                doneFn);
              return state.animator.end();
            } else {
              state.height = height;
              return generateRunner(false,
                state,
                animator,
                element,
                doneFn)();
            }
          }
        }
        doneFn();
      }
    };
}]);
4

3 回答 3

0

这是我现在使用的。这是一个将父元素的高度设置为的指令,auto以便它在切换时与子列表高度展开或收缩。如果父列表被切换,高度将被重新计算为其动画的正常值。

app.directive('toggleParent', function () {
    return {
        restrict: 'C',
        compile: function (element, attr) {

            return function (scope, element) {
                element.on('click', function (event) {
                    $(this).closest('.slide-toggle').css('height', 'auto');
                });
            }
        }
    }
});

CodePen 演示

我确信同样的功能可以用动画来实现。这就是我真正想要帮助的。

于 2015-10-29T21:05:01.657 回答
0

您只需要在此处添加 else 语句:

if (closing && state.doneFn === doneFn) {
    element[0].style.height = '';
} else {
    element[0].style.height = 'auto';
}

这样,在动画完成后,高度设置为自动,这样就可以在任意多个级别上解决所有问题。

于 2017-06-26T18:32:49.730 回答
0

如果你想做不止一层,你可以使用这个:

jQuery

app.directive('toggleParents', function () {
    return {
        compile: function (element, attr) {

            return function (scope, element) {
                element.on('click', function (event) {
                    $(this).parents('.slide-toggle').css('height', 'auto');
                });
            }
        }
    }
});

原生 JS

app.directive('toggleParents', function() {
    return {
      compile: function(element, attr) {
        var parents = function(el, cls) {
              var els = [];

              while (el = el.parentElement) {
                var hasClass = el.classList.contains(cls);

                if (hasClass) {
                  els.push(el);
                }
              }
              return els;
            };
        return function(scope, element) {
          element.on('click', function(event) {

            angular.element(parents(element[0], 'slide-toggle')).css('height', 'auto');
          });
        };
      }
    };   
});
于 2016-01-05T19:49:47.367 回答