Instantly share code, notes, and snippets.
Created
July 18, 2014 09:41
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save kazukitanaka0611/a12d1633644ccb4f23fa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static CGFloat const SideHelperView = 2.0; | |
static CGFloat const AnimationDuration = .5; | |
struct Animation { | |
NSTimeInterval sideDelay; | |
NSTimeInterval sideDumping; | |
NSTimeInterval sideVelocity; | |
NSTimeInterval centerDelay; | |
NSTimeInterval centerDumping; | |
NSTimeInterval centerVelocity; | |
}; | |
@interface AnimationView() | |
@property (nonatomic, strong) UIView *menuView; | |
@property (nonatomic, strong) UIView *sideAnchorView; | |
@property (nonatomic, strong) UIView *centerAnchorView; | |
@property (nonatomic, strong) UIColor *fillColor; | |
@property (nonatomic, strong) CADisplayLink *displayLink; | |
@end | |
@implementation AnimationView | |
struct Animation animation; | |
- (instancetype)initWithMenuView:(UIView *)menuView animationType:(AnimationType)animationType | |
{ | |
CGRect fakeRect = menuView.frame; | |
fakeRect.size.height += 25.0; | |
if (self = [super initWithFrame:fakeRect]) | |
{ | |
self.menuView = menuView; | |
self.sideAnchorView = [[UIView alloc] initWithFrame: | |
CGRectMake(-SideHelperView / 2.0, -SideHelperView / 2.0, | |
SideHelperView, SideHelperView)]; | |
self.centerAnchorView = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width / 2.0 - SideHelperView / 2.0, | |
-SideHelperView / 2.0, | |
SideHelperView, SideHelperView)]; | |
self.menuView.frame = CGRectMake(0, -self.menuView.frame.size.height, | |
self.menuView.frame.size.width, self.menuView.frame.size.height); | |
self.fillColor = menuView.backgroundColor; | |
self.backgroundColor = [UIColor clearColor]; | |
self.menuView.backgroundColor = [UIColor clearColor]; | |
[self setValuesForAnimationType:animationType]; | |
_isAnimating = NO; | |
_isShow = NO; | |
} | |
return self; | |
} | |
// Only override drawRect: if you perform custom drawing. | |
// An empty implementation adversely affects performance during animation. | |
- (void)drawRect:(CGRect)rect | |
{ | |
// Drawing code | |
if (self.menuView.subviews) | |
{ | |
[self addSubview:self.menuView]; | |
[self addSubview:self.centerAnchorView]; | |
[self addSubview:self.sideAnchorView]; | |
} | |
CALayer *sideLayer = self.sideAnchorView.layer.presentationLayer; | |
CALayer *centerLayer = self.centerAnchorView.layer.presentationLayer; | |
CGPoint sideLayerCenterPoint = CGPointMake(sideLayer.frame.origin.x + sideLayer.frame.size.width / 2.0, | |
sideLayer.frame.origin.y + sideLayer.frame.size.height / 2.0); | |
CGPoint centerLayerCenterPoint = CGPointMake(centerLayer.frame.origin.x + centerLayer.frame.size.width / 2.0, | |
centerLayer.frame.origin.y + centerLayer.frame.size.height / 2.0); | |
UIBezierPath *path = [UIBezierPath bezierPath]; | |
[path moveToPoint:sideLayerCenterPoint]; | |
[path addQuadCurveToPoint:CGPointMake(sideLayerCenterPoint.x + self.menuView.frame.size.width, | |
sideLayerCenterPoint.y) | |
controlPoint:centerLayerCenterPoint]; | |
[path addLineToPoint:CGPointMake(self.menuView.frame.size.width, 0)]; | |
[path addLineToPoint:CGPointMake(0, 0)]; | |
[path closePath]; | |
CGContextRef context = UIGraphicsGetCurrentContext(); | |
CGContextAddPath(context, path.CGPath); | |
[self.fillColor setFill]; | |
CGContextFillPath(context); | |
} | |
#pragma mark - public method | |
- (void)show | |
{ | |
[self animateMenuViewTopAppear:YES]; | |
} | |
- (void)hide | |
{ | |
[self animateMenuViewTopAppear:NO]; | |
} | |
#pragma mark - private method | |
- (void)setValuesForAnimationType:(AnimationType)animationType | |
{ | |
switch (animationType) { | |
case AnimationTypeBounce: { | |
animation.sideDelay = .1; | |
animation.sideDumping = .4; | |
animation.sideVelocity = .9; | |
animation.centerDelay = 0; | |
animation.centerDumping = .6; | |
animation.centerVelocity = .6; | |
} | |
break; | |
case AnimationTypeSoftBounce: { | |
animation.sideDelay = .1; | |
animation.sideDumping = .6; | |
animation.sideVelocity = .6; | |
animation.centerDelay = 0; | |
animation.centerDumping = .6; | |
animation.centerVelocity = .6; | |
} | |
break; | |
case AnimationTypeHardBounce: { | |
animation.sideDelay = .1; | |
animation.sideDumping = .3; | |
animation.sideVelocity = .7; | |
animation.centerDelay = 0; | |
animation.centerDumping = .6; | |
animation.centerVelocity = .4; | |
} | |
break; | |
case AnimationTypeWave: { | |
animation.sideDelay = .0; | |
animation.sideDumping = .5; | |
animation.sideVelocity = .5; | |
animation.centerDelay = .1; | |
animation.centerDumping = .5; | |
animation.centerVelocity = .5; | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
- (void)animateMenuViewTopAppear:(BOOL)needsToAppear | |
{ | |
if (_isShow != needsToAppear && !_isAnimating) | |
{ | |
_isAnimating = YES; | |
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)]; | |
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; | |
[UIView animateWithDuration:AnimationDuration | |
delay:animation.sideDelay | |
usingSpringWithDamping:animation.sideDumping | |
initialSpringVelocity:animation.sideVelocity | |
options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction) animations:^{ | |
if (needsToAppear) | |
{ | |
self.sideAnchorView.frame = CGRectMake(self.sideAnchorView.frame.origin.x, | |
self.menuView.frame.size.height - SideHelperView / 2.0, SideHelperView, SideHelperView); | |
self.menuView.frame = CGRectMake(self.menuView.frame.origin.x, 0, | |
self.menuView.frame.size.width, | |
self.menuView.frame.size.height); | |
} | |
else | |
{ | |
self.sideAnchorView.frame = CGRectMake(self.sideAnchorView.frame.origin.x, | |
SideHelperView / 2.0, | |
SideHelperView, | |
SideHelperView); | |
} | |
} completion:^(BOOL finished) { | |
[self.displayLink invalidate]; | |
self.displayLink = nil; | |
_isShow = needsToAppear; | |
_isAnimating = NO; | |
}]; | |
[UIView animateWithDuration:AnimationDuration | |
delay:animation.centerDelay | |
usingSpringWithDamping:animation.centerDumping | |
initialSpringVelocity:animation.centerVelocity | |
options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction) animations:^{ | |
if (needsToAppear) | |
{ | |
self.centerAnchorView.frame = CGRectMake(self.centerAnchorView.frame.origin.x, | |
self.menuView.frame.size.height - SideHelperView / 2.0, SideHelperView, SideHelperView); | |
} | |
else | |
{ | |
self.centerAnchorView.frame = CGRectMake(self.centerAnchorView.frame.origin.x, | |
-SideHelperView / 2.0, | |
SideHelperView, | |
SideHelperView); | |
self.menuView.frame = CGRectMake(self.menuView.frame.origin.x, | |
-self.menuView.frame.size.height, | |
self.menuView.frame.size.width, | |
self.menuView.frame.size.height); | |
} | |
} completion:nil]; | |
} | |
} | |
- (void)tick:(CADisplayLink *)displayLink | |
{ | |
[self setNeedsDisplay]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment