Created
December 24, 2011 21:38
-
-
Save hunterbridges/1518411 to your computer and use it in GitHub Desktop.
Golfball Grippies
This file contains 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
#import <UIKit/UIKit.h> | |
typedef enum { | |
kGolfballGrippiesAnimationNone = 0, | |
kGolfballGrippiesAnimationLeft, | |
kGolfballGrippiesAnimationRight | |
} GolfballGrippiesAnimation; | |
@interface GolfballGrippies : UIView { | |
GolfballGrippiesAnimation currentAnimation_; | |
CGPoint startTouchPosition_; | |
CGFloat cellPadding_; | |
CGFloat cellSize_; | |
NSSet *touches_; | |
CGSize cachedOuterSize_; | |
UIScrollView *scrollViewLeft_; | |
UIScrollView *scrollViewRight_; | |
CGPoint scrollViewLeftStart_; | |
CGPoint scrollViewRightStart_; | |
int animationStep_; | |
int animationTrail_; | |
NSTimer *animationTimer_; | |
BOOL enabled_; | |
} | |
@property (nonatomic, assign) UIScrollView *scrollViewLeft; | |
@property (nonatomic, assign) UIScrollView *scrollViewRight; | |
@property (nonatomic, assign) GolfballGrippiesAnimation currentAnimation; | |
@property (nonatomic, assign) CGFloat cellPadding; | |
@property (nonatomic, assign) CGFloat cellSize; | |
@property (nonatomic, assign) BOOL enabled; | |
@property (nonatomic, readonly) int columnCount; | |
@property (nonatomic, readonly) int rowCount; | |
@property (nonatomic, readonly) CGSize cellOuterSize; | |
@end |
This file contains 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
#import "GolfballGrippies.h" | |
@implementation GolfballGrippies | |
@synthesize currentAnimation = currentAnimation_; | |
@synthesize cellPadding = cellPadding_; | |
@synthesize cellSize = cellSize_; | |
@synthesize enabled = enabled_; | |
@synthesize scrollViewLeft = scrollViewLeft_; | |
@synthesize scrollViewRight = scrollViewRight_; | |
- (id)initWithFrame:(CGRect)frame { | |
self = [super initWithFrame:frame]; | |
if (self) { | |
self.backgroundColor = [UIColor clearColor]; | |
self.opaque = NO; | |
cellSize_ = 8.0; | |
cellPadding_ = 2.0; | |
touches_ = nil; | |
cachedOuterSize_ = CGSizeZero; | |
animationTrail_ = 10; | |
animationStep_ = -animationTrail_; | |
} | |
return self; | |
} | |
- (void)setScrollViewLeft:(UIScrollView *)scrollViewLeft{ | |
scrollViewLeft_ = scrollViewLeft; | |
} | |
- (void)setScrollViewRight:(UIScrollView *)scrollViewRight{ | |
scrollViewRight_ = scrollViewRight; | |
} | |
- (void)setCurrentAnimation:(GolfballGrippiesAnimation)currentAnimation { | |
currentAnimation_ = currentAnimation; | |
if (currentAnimation == kGolfballGrippiesAnimationNone) { | |
if (animationTimer_) { | |
[animationTimer_ invalidate]; | |
} | |
animationTimer_ = nil; | |
[self setNeedsDisplay]; | |
} else { | |
animationStep_ = -animationTrail_; | |
animationTimer_ = [NSTimer scheduledTimerWithTimeInterval:0.03 | |
target:self | |
selector:@selector(animate) | |
userInfo:nil | |
repeats:YES]; | |
} | |
} | |
- (void)dealloc { | |
[touches_ release]; | |
if (animationTimer_) { | |
[animationTimer_ invalidate]; | |
} | |
[animationTimer_ release]; | |
[super dealloc]; | |
} | |
- (CGSize)cellOuterSize { | |
if (!CGSizeEqualToSize(cachedOuterSize_, CGSizeZero)) return cachedOuterSize_; | |
cachedOuterSize_ = CGSizeMake(cellSize_ + 2 * cellPadding_, | |
cellSize_ + 2 * cellPadding_); | |
return cachedOuterSize_; | |
} | |
- (void)animate { | |
switch (currentAnimation_) { | |
case kGolfballGrippiesAnimationLeft: | |
case kGolfballGrippiesAnimationRight: | |
animationStep_++; | |
if (animationStep_ > self.columnCount + animationTrail_) { | |
animationStep_ = -animationTrail_; | |
} | |
[self setNeedsDisplay]; | |
break; | |
case kGolfballGrippiesAnimationNone: | |
animationStep_ = 0; | |
break; | |
} | |
} | |
- (void)drawRect:(CGRect)rect { | |
int lightUpColumn; | |
int rowMin = floorf(rect.origin.x / self.cellOuterSize.width); | |
int rowMax = floorf((rect.size.width + rect.origin.x) / | |
self.cellOuterSize.width); | |
int colMin = floorf(rect.origin.y / self.cellOuterSize.height); | |
int colMax = floorf((rect.size.height + rect.origin.y) / | |
self.cellOuterSize.height); | |
for (int row = rowMin; row < rowMax; row++) { | |
for (int col = colMin; col < colMax; col++) { | |
// NSDate *startDate = [NSDate date]; | |
CGRect circleRect = CGRectMake(self.cellOuterSize.width * col + | |
cellPadding_, | |
self.cellOuterSize.height * row + | |
cellPadding_, | |
cellSize_, | |
cellSize_); | |
CGPoint circleCenter = CGPointMake(circleRect.origin.x + | |
circleRect.size.width / 2.0, | |
circleRect.origin.y + | |
circleRect.size.height / 2.0); | |
CGFloat shade = 0.8; | |
if (touches_ != nil && [touches_ count] > 0) { | |
for (UITouch *touch in touches_) { | |
CGPoint point = [touch locationInView:self]; | |
CGFloat distance = sqrtf(powf(circleCenter.x - point.x, 2) + | |
powf(circleCenter.y - point.y, 2)); | |
if (distance < 50.0) { | |
shade = MIN(shade, 0.7); | |
} | |
} | |
} | |
switch (currentAnimation_) { | |
case kGolfballGrippiesAnimationLeft: | |
lightUpColumn = self.columnCount - animationStep_; | |
if (lightUpColumn >= col && lightUpColumn <= col + animationTrail_) { | |
int distance = abs(lightUpColumn - col); | |
CGFloat darken = 0.1; | |
shade = MIN(shade, 0.8 - (darken * distance / animationTrail_)); | |
} | |
break; | |
case kGolfballGrippiesAnimationRight: | |
if (animationStep_ <= col && animationStep_ >= col - animationTrail_) { | |
int distance = abs(animationStep_ - col); | |
CGFloat darken = 0.1; | |
shade = MIN(shade, 0.8 - (darken * distance / animationTrail_)); | |
} | |
break; | |
case kGolfballGrippiesAnimationNone: | |
break; | |
} | |
// Light bottom | |
UIBezierPath *light = [UIBezierPath bezierPathWithRect: | |
CGRectMake(circleRect.origin.x, | |
circleRect.origin.y + 1, | |
circleRect.size.width, | |
circleRect.size.height)]; | |
[[UIColor colorWithWhite:0.95 alpha:1] setFill]; | |
[light fill]; | |
UIBezierPath *shadow = [UIBezierPath bezierPathWithRect:circleRect]; | |
[[UIColor colorWithWhite:0.65 alpha:1] setFill]; | |
[shadow fill]; | |
UIBezierPath *fill = [UIBezierPath bezierPathWithRect: | |
CGRectMake(circleRect.origin.x, | |
circleRect.origin.y + 1, | |
circleRect.size.width, | |
circleRect.size.height - 1)]; | |
[[UIColor colorWithWhite:shade alpha:1] setFill]; | |
[fill fill]; //lulz | |
} | |
} | |
} | |
- (int)columnCount { | |
return floor(self.frame.size.width / self.cellOuterSize.width); | |
} | |
- (int)rowCount { | |
return floor(self.frame.size.height / self.cellOuterSize.height); | |
} | |
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { | |
[super touchesBegan:touches withEvent:event]; | |
UITouch *touch = [touches anyObject]; | |
// startTouchPosition is an instance variable | |
if (enabled_) { | |
startTouchPosition_ = [touch locationInView:self]; | |
scrollViewLeftStart_ = scrollViewLeft_.contentOffset; | |
scrollViewRightStart_ = scrollViewRight_.contentOffset; | |
} | |
if (enabled_) { | |
[touches_ release]; | |
touches_ = [touches retain]; | |
[self setNeedsDisplay]; | |
} | |
} | |
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { | |
[super touchesCancelled:touches withEvent:event]; | |
if (enabled_) { | |
[scrollViewLeft_ setContentOffset:scrollViewLeftStart_ animated:YES]; | |
[scrollViewRight_ setContentOffset:scrollViewRightStart_ animated:YES]; | |
} | |
[touches_ release]; | |
touches_ = nil; | |
} | |
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { | |
[super touchesEnded:touches withEvent:event]; | |
UITouch *touch = [touches anyObject]; | |
CGPoint currentTouchPosition = [touch locationInView:self]; | |
if (enabled_) { | |
float swipePercentage; | |
if (currentTouchPosition.x > startTouchPosition_.x) { | |
//Swiping Right | |
swipePercentage = (currentTouchPosition.x - startTouchPosition_.x) / | |
(self.frame.size.width - startTouchPosition_.x); | |
if ((swipePercentage>0.5)&& | |
((scrollViewRightStart_.x - scrollViewRight_.frame.size.width)>=0)) { | |
//full swipe | |
[scrollViewRight_ setContentOffset: | |
CGPointMake((scrollViewRightStart_.x - scrollViewRight_.frame.size.width) | |
, 0) animated:YES]; | |
} else { | |
//swipe cancelled | |
[scrollViewRight_ setContentOffset:scrollViewRightStart_ animated:YES]; | |
} | |
} else { | |
//Swiped Left | |
swipePercentage = (startTouchPosition_.x - currentTouchPosition.x) / | |
startTouchPosition_.x; | |
if ((fabsf(swipePercentage)>0.5)&& | |
((scrollViewLeftStart_.x + scrollViewLeft_.frame.size.width) | |
< scrollViewLeft_.contentSize.width)) | |
{ | |
//full swipe | |
[scrollViewLeft_ setContentOffset: | |
CGPointMake((scrollViewLeftStart_.x + scrollViewLeft_.frame.size.width) | |
, 0) animated:YES]; | |
} else { | |
//swipe cancelled | |
[scrollViewLeft_ setContentOffset:scrollViewLeftStart_ animated:YES]; | |
} | |
} | |
scrollViewLeftStart_ = scrollViewLeft_.contentOffset; | |
scrollViewRightStart_ = scrollViewRight_.contentOffset; | |
} | |
[touches_ release]; | |
touches_ = nil; | |
} | |
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { | |
[super touchesMoved:touches withEvent:event]; | |
UITouch *touch = [touches anyObject]; | |
CGPoint currentTouchPosition = [touch locationInView:self]; | |
if (enabled_) { | |
float swipePercentage; | |
if (currentTouchPosition.x > startTouchPosition_.x) { | |
//Swiping Right | |
swipePercentage = (currentTouchPosition.x - startTouchPosition_.x) / | |
(self.frame.size.width - startTouchPosition_.x); | |
float newContentOffset = scrollViewRightStart_.x - | |
(scrollViewRight_.frame.size.width * swipePercentage); | |
if (newContentOffset < -100) { | |
[scrollViewRight_ setContentOffset:scrollViewRightStart_ animated:YES]; | |
}else if(swipePercentage <= 1.2){ | |
[scrollViewRight_ setContentOffset: | |
CGPointMake(newContentOffset, 0) animated:NO]; | |
} | |
} else { | |
//Swiping Left | |
swipePercentage = (startTouchPosition_.x - currentTouchPosition.x) / | |
startTouchPosition_.x; | |
float newContentOffset = (scrollViewLeft_.frame.size.width | |
* swipePercentage) + scrollViewLeftStart_.x; | |
if (newContentOffset > | |
((scrollViewLeft_.contentSize.width-scrollViewLeft_.frame.size.width) | |
+ 100)) { | |
//Cancel | |
[scrollViewLeft_ setContentOffset:scrollViewLeftStart_ animated:YES]; | |
} else if (swipePercentage <= 1.2){ | |
[scrollViewLeft_ setContentOffset: | |
CGPointMake(newContentOffset, 0) animated:NO]; | |
} | |
} | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment