1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ios/chrome/browser/ui/animation_util.h"
10 #include "ios/chrome/browser/ui/reversed_animation.h"
12 CAAnimation* FrameAnimationMake(CALayer* layer,
15 CGRect beginBounds = {CGPointZero, beginFrame.size};
16 CGRect endBounds = {CGPointZero, endFrame.size};
17 CABasicAnimation* boundsAnimation =
18 [CABasicAnimation animationWithKeyPath:@"bounds"];
19 boundsAnimation.fromValue = [NSValue valueWithCGRect:beginBounds];
20 boundsAnimation.toValue = [NSValue valueWithCGRect:endBounds];
21 boundsAnimation.removedOnCompletion = NO;
22 boundsAnimation.fillMode = kCAFillModeBoth;
23 CGPoint beginPosition = CGPointMake(
24 beginFrame.origin.x + layer.anchorPoint.x * beginBounds.size.width,
25 beginFrame.origin.y + layer.anchorPoint.y * beginBounds.size.height);
26 CGPoint endPosition = CGPointMake(
27 endFrame.origin.x + layer.anchorPoint.x * endBounds.size.width,
28 endFrame.origin.y + layer.anchorPoint.y * endBounds.size.height);
29 CABasicAnimation* positionAnimation =
30 [CABasicAnimation animationWithKeyPath:@"position"];
31 positionAnimation.fromValue = [NSValue valueWithCGPoint:beginPosition];
32 positionAnimation.toValue = [NSValue valueWithCGPoint:endPosition];
33 positionAnimation.removedOnCompletion = NO;
34 positionAnimation.fillMode = kCAFillModeBoth;
35 return AnimationGroupMake(@[ boundsAnimation, positionAnimation ]);
38 CAAnimation* OpacityAnimationMake(CGFloat beginOpacity, CGFloat endOpacity) {
39 CABasicAnimation* opacityAnimation =
40 [CABasicAnimation animationWithKeyPath:@"opacity"];
41 opacityAnimation.fromValue = @(beginOpacity);
42 opacityAnimation.toValue = @(endOpacity);
43 opacityAnimation.fillMode = kCAFillModeBoth;
44 opacityAnimation.removedOnCompletion = NO;
45 return opacityAnimation;
48 CAAnimation* AnimationGroupMake(NSArray* animations) {
49 CAAnimationGroup* animationGroup = [CAAnimationGroup animation];
50 animationGroup.animations = animations;
51 CFTimeInterval duration = 0.0;
52 for (CAAnimation* animation in animations)
53 duration = std::max(duration, animation.beginTime + animation.duration);
54 animationGroup.duration = duration;
55 animationGroup.fillMode = kCAFillModeBoth;
56 animationGroup.removedOnCompletion = NO;
57 return animationGroup;
60 CAAnimation* DelayedAnimationMake(CAAnimation* animation,
61 CFTimeInterval delay) {
62 CAAnimation* delayedAnimation = [[animation copy] autorelease];
63 if (delayedAnimation) {
64 delayedAnimation.beginTime = delay;
65 delayedAnimation = AnimationGroupMake(@[ delayedAnimation ]);
67 return delayedAnimation;
70 CABasicAnimation* FindAnimationForKeyPath(NSString* keyPath,
71 CAAnimation* animation) {
72 __block CABasicAnimation* animationForKeyPath = nil;
73 if ([animation isKindOfClass:[CABasicAnimation class]]) {
74 CABasicAnimation* basicAnimation =
75 static_cast<CABasicAnimation*>(animation);
76 if ([basicAnimation.keyPath isEqualToString:keyPath])
77 animationForKeyPath = basicAnimation;
78 } else if ([animation isKindOfClass:[CAAnimationGroup class]]) {
79 CAAnimationGroup* animationGroup =
80 static_cast<CAAnimationGroup*>(animation);
81 [animationGroup.animations
82 enumerateObjectsUsingBlock:^(CAAnimation* subAnimation, NSUInteger idx,
84 animationForKeyPath = FindAnimationForKeyPath(keyPath, subAnimation);
85 *stop = animationForKeyPath != nil;
88 return animationForKeyPath;
91 void RemoveAnimationForKeyFromLayers(NSString* key, NSArray* layers) {
92 for (CALayer* layer in layers)
93 [layer removeAnimationForKey:key];