Skip to content

Instantly share code, notes, and snippets.

@hunterbridges
Created December 24, 2011 21:38
Show Gist options
  • Save hunterbridges/1518411 to your computer and use it in GitHub Desktop.
Save hunterbridges/1518411 to your computer and use it in GitHub Desktop.
Golfball Grippies
#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
#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