AngularJS - 找到折叠动画的结束
Posted
技术标签:
【中文标题】AngularJS - 找到折叠动画的结束【英文标题】:AngularJS - Find end of collapse animation 【发布时间】:2014-11-29 13:51:22 【问题描述】:我对@987654321@ 的collapse
指令有一个简单的问题。我有一个<select>
菜单。当有人更改菜单时,内容也会发生变化。但是,我想在应用这些更改之前添加一个动画。具体来说,我希望该部分在显示新内容之前折叠和取消折叠。我可以折叠它,但我想知道如何检测折叠何时完成,以便我可以展开它。
我可以使用我目前使用的$timeout
方法,但是感觉“hackish”和“不正确”,因为如果折叠动画的时间发生变化,那么我必须再次更改时间。
相关代码:
.directive("myBufferAnimation", function($timeout)
var ignoreFirst = true;
return function(scope, element, attrs)
scope.$watch("selectBuffer", function(newValue)
if (ignoreFirst)
ignoreFirst = false;
return;
scope.toCollapse = true;
// Detect end of animation here?
// Bogus solution, as this just waits for one second rather than listening for the end of animation
$timeout(function()
scope.selected = newValue;
scope.toCollapse = false;
, 1000);
);
);
这个jsfiddle 说明了问题。
【问题讨论】:
【参考方案1】:查看 angularui bootstrap 的 collapse 指令,它使用 $transition 服务执行动画,但它不会暴露以挂钩到服务返回的承诺。但是,它确实会更改具有collapse
指令的元素的类名。您可以通过在元素的 class 属性上放置一个监视来使用它来确定折叠动画何时完成。
下面是在元素上监视类的代码的工作示例。我进行了更改以使用ng-change
来执行动画,而不是观看selectBuffer
。这消除了对 ignoreFirst
变量的需要。
angular.module("testApp", ["ui.bootstrap"]).controller("TestCtrl", function($scope)
// This would actually be fetched from an ajax call
$scope.data = [
"title": "Title 1",
"content": "Content 1"
,
"title": "The Second Title",
"content": "Some content goes here"
,
"title": "Title 3",
"content": "Content 3"
];
$scope.selected = $scope.data[0];
$scope.selectBuffer = $scope.data[0];
$scope.toCollapse = false;
).directive("myBufferAnimation", function($timeout)
return function(scope, element, attrs)
scope.valueChanged = function()
scope.toCollapse = true;
// save off the unregister method returned from $watch call.
var unregisterWatch = scope.$watch(function()
return element.attr('class');
, function(newClass, oldClass)
// If the newClass is 'collapse' and the oldClass is 'collapsing'
// this means that the collapsing animation has completed.
if (newClass.indexOf("collapse") !== -1 && oldClass.indexOf("collapsing") !== -1)
scope.selected = scope.selectBuffer;
scope.toCollapse = false;
// unregister the $watch on the class attribute
// since it is no longer needed.
unregisterWatch();
);
;
);
<!DOCTYPE html>
<html>
<head>
<link data-require="bootstrap-css@3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script src="https://code.angularjs.org/1.2.26/angular.js"></script>
<script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script data-require="bootstrap@3.1.1" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script data-require="angular-ui-bootstrap@0.11.0" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
</head>
<body>
<div ng-app="testApp">
<div ng-controller="TestCtrl">
<select ng-options="opt as opt.title for opt in data" ng-model="selectBuffer" ng-change="valueChanged()"></select>
<br />
<div my-buffer-animation="" collapse="toCollapse" class="test">
<h1>selected.title</h1>
<p>selected.content</p>
</div>
</div>
</div>
</body>
</html>
【讨论】:
我注意到你使用了newClass === "collapse"
。即使有其他类,这也能工作(因为newClass
可能是"collapse my-custom-class"
或其他东西,对吧?)
更新最后一条评论:我将 test-class
添加到 div
和 my-buffer-animation
指令和上面的代码停止工作,但我认为这可以使用 element.hasClass
或等效解决。
我尝试测试您建议的更改,但我在使用的浏览器中遇到错误,这可能是由于使用了 classList
以及 angularjs 获取旧值以传递给 watch 函数的方式.我改为使用indexOf
来确定是否存在应该处理具有多个类名的类名。 indexOf
可能对每种情况都不够健壮,但对于您正在做的事情应该足够了。以上是关于AngularJS - 找到折叠动画的结束的主要内容,如果未能解决你的问题,请参考以下文章