作为一个例子,我有一个ng-view动画,我有几个内容元素。我希望在视图动画完成后运行内容动画。目前我在内容元素上使用ng-hide,然后在ng-view-enter完成时设置范围变量。它不完全是一个优雅的完整解决方案。显然我可以将所有动画添加到ng-view-enter中,但是我希望保留单独的指令以使代码可重用。以下是使用TweenMax的示例:
//<ng-view class="animate-view"></ng-view>
app.animation('.animate-view', [ function () {
var obj = {};
obj.enter = function(element, done){
var $scope = angular.element(element).scope();
console.log("15","obj","enter", $scope);
var tm = new TimelineMax();
tm.from(element.find('section'), 0.3, {scaleX:0});
tm.add(done);
tm.add(function(){
$scope.$apply(function(){
$scope.viewReady=true;
});
}, "+=0.1");
}
return obj;
}]);
//<div class="animate-heading" ng-hide="!viewReady" >Heading 1</div>
app.animation('.animate-heading', [ function () {
var obj = {};
obj.beforeRemoveClass = function (element, className, done) {
var $scope = angular.element(element).scope();
if(className == "ng-hide"){
var tm = new TimelineMax();
tm.from(element, 0.4, {opacity:0});
tm.add(done);
tm.add(function(){
$scope.$apply(function(){
$scope.headingReady=true;
});
}, "+=0.1");
}
}
return obj;
}]);
答案 0 :(得分:0)
Thomas Burleson对此post的阅读真的迫使我重新考虑Angular中的动画。我认为使用某种服务肯定是要走的路。但是,我知道的唯一真正做到这一点的例子是gsTimelines和ngFx。
ngFx使用ngAnimate从注入的服务创建新动画。这里有一个小小的演示,展示了它是如何工作的。此演示中有2个动画模块,.shake
执行addClass
个动画,.block
执行enter
个动画。调用这些动画时,它们会创建一个新的TweenBuilder,根据存储在TweenBuilder服务中的可配置动画创建时间轴。
angular
.module("app", ["ngAnimate"])
.controller("MainController", MainController)
.animation(".block", blockAnimation)
.animation(".shake", shakeAnimation)
.factory("TweenBuilder", TweenBuilder);
function MainController($timeout) {
var vm = this;
vm.show = false;
vm.shake = false;
vm.shakeBlock = function() {
if (vm.shake) vm.shake = false;
$timeout(function() { vm.shake = true; });
};
vm.addBlock = function() {
if (vm.show) vm.show = false;
$timeout(function() { vm.show = true; });
};
}
function shakeAnimation(TweenBuilder) {
var tweens = [
{ name: "shake", options: { x: 2, y: 2, repeat: 50 }}
];
return new TweenBuilder({ addClass: tweens });
}
function blockAnimation(TweenBuilder) {
var tweens = [
{ name: "slide", type: "from", duration: 0.5, label: "0", options: { x: window.innerWidth / 4 }},
{ name: "fade", type: "to", duration: 1.0, label: "0", options: { autoAlpha: 1 }},
{ name: "scale", type: "from", duration: 0.5, label: "0", options: { scale: 0.2 }},
{ name: "slide", type: "staggerFrom", duration: 0.5, label: "0.1", element: ".block div", stagger: 0.05, options: { x: 100 }},
];
return new TweenBuilder({ enter: tweens });
}
function TweenBuilder() {
var animation = {
slide: function(element, tween) {
return TweenMax[tween.type](element, tween.duration, { x: tween.options.x, y: tween.options.y }, tween.stagger);
},
scale: function(element, tween) {
return TweenMax[tween.type](element, tween.duration, { scale: tween.options.scale });
},
fade: function(element, tween) {
return TweenMax[tween.type](element, tween.duration, { autoAlpha: tween.options.autoAlpha });
},
shake: function(element, tween) {
var x = tween.options.x, y = tween.options.y;
return TweenMax.fromTo(element, 0.01, {x: -x, y: y}, {x: x, y: -y, clearProps: "x,y", repeat: tween.options.repeat });
},
};
return function(config) {
var className, done;
this.enter = angular.bind(this, buildTweens, "enter");
this.addClass = angular.bind(this, buildTweens, "addClass");
function buildTweens(type, element) {
done = type === "addClass"
? (className = arguments[2], arguments[3])
: arguments[2];
if (!config[type]) {
done(); return;
}
config[type].reduce(function(timeline, tween) {
return timeline
.add(animation[tween.name](tween.element || element, tween), tween.label);
}, new TimelineMax({ onComplete: done }));
}
};
}
&#13;
body {
padding: 25px;
overflow: hidden;
}
.block {
position:relative;
padding: 15px;
opacity: 0;
visibility: hidden;
}
.block > div {
padding: 5px;
}
&#13;
<!DOCTYPE html>
<html ng-app="app">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css" />
<link rel="stylesheet" href="style.css" />
</head>
<body ng-cloak>
<div ng-controller="MainController as vm">
<div>
<button class="btn btn-default" ng-click="vm.addBlock()">Add Block</button>
<button class="btn btn-default" ng-click="vm.shakeBlock()">Shake Block</button>
</div>
<div class="block" ng-if="vm.show" ng-class="{ shake: vm.shake }">
<h1>Lorem ipsum dolor sit amet.</h1>
<hr>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
</div>
</div>
<!-- vendor -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.15.0/TweenMax.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-animate.min.js"></script>
<!-- app -->
<script src="app.js"></script>
</body>
</html>
&#13;
答案 1 :(得分:-1)
使用promises找到了一个很好的例子 https://github.com/ThomasBurleson/angularjs-gsTimelines#the-koda-application