Advertisement
ZaBlanc

iOS Clock Using Layers

Nov 7th, 2011
10,732
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. //  ClockView.h
  3. //
  4.  
  5. #import <UIKit/UIKit.h>
  6.  
  7. @interface ClockView : UIControl {
  8.     NSTimer *updateTimer_;
  9.    
  10.     CAShapeLayer *hourHand_;
  11.     CAShapeLayer *minuteHand_;
  12.     CAShapeLayer *secondHand_;
  13. }
  14.  
  15. - (void)startUpdates;
  16. - (void)stopUpdates;
  17.  
  18. @end
  19.  
  20.  
  21.  
  22.  
  23.  
  24. //
  25. //  ClockView.m
  26. //
  27.  
  28. #import "ClockView.h"
  29.  
  30. @implementation ClockView
  31.  
  32. - (id)initWithCoder:(NSCoder *)aDecoder {
  33.     if ((self = [super initWithCoder:aDecoder])) {
  34.         [self setUpClock];
  35.     }
  36.                  
  37.     return self;
  38. }
  39.  
  40. - (void)setUpClock {
  41.     CAShapeLayer *face = [CAShapeLayer layer];
  42.    
  43.     // face
  44.     face.bounds = self.bounds;
  45.     face.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  46.    
  47.     face.fillColor = [[UIColor grayColor] CGColor];
  48.     face.strokeColor = [[UIColor blackColor] CGColor];
  49.     face.lineWidth = 4.0;
  50.    
  51.     CGMutablePathRef path = CGPathCreateMutable();
  52.     CGPathAddEllipseInRect(path, nil, self.bounds);
  53.     face.path = path;
  54.    
  55.     [self.layer addSublayer:face];
  56.    
  57.     // numbers
  58.     for (NSInteger i=1; i <= 12; ++i) {
  59.         CATextLayer *number = [CATextLayer layer];
  60.         number.string = [NSString stringWithFormat:@"%i", i];
  61.         number.alignmentMode = @"center";
  62.         number.fontSize = 18.0;
  63.         number.foregroundColor = [[UIColor blackColor] CGColor];
  64.         number.bounds = CGRectMake(0.0, 0.0, 25.0, self.bounds.size.height / 2.0 - 10.0);
  65.         number.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  66.         number.anchorPoint = CGPointMake(0.5, 1.0);
  67.         number.transform = CATransform3DMakeRotation((M_PI * 2) / 12.0 * i, 0, 0, 1);
  68.        
  69.         [self.layer addSublayer:number];
  70.     }    
  71.    
  72.     // ticks
  73.     for (NSInteger i=1; i <= 60; ++i) {
  74.         CAShapeLayer *tick = [CAShapeLayer layer];
  75.        
  76.         path = CGPathCreateMutable();
  77.         CGPathAddEllipseInRect(path, nil, CGRectMake(0.0, 0.0, 1.0, 5.0));
  78.        
  79.         tick.strokeColor = [[UIColor blackColor] CGColor];
  80.         tick.bounds = CGRectMake(0.0, 0.0, 1.0, self.bounds.size.height / 2.0);
  81.         tick.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  82.         tick.anchorPoint = CGPointMake(0.5, 1.0);
  83.         tick.transform = CATransform3DMakeRotation((M_PI * 2) / 60.0 * i, 0, 0, 1);
  84.         tick.path = path;
  85.        
  86.         [self.layer addSublayer:tick];
  87.     }    
  88.    
  89.     // second hand
  90.     secondHand_ = [CAShapeLayer layer];
  91.    
  92.     path = CGPathCreateMutable();
  93.     CGPathMoveToPoint(path, nil, 1.0, 0.0);
  94.     CGPathAddLineToPoint(path, nil, 1.0, self.bounds.size.height / 2.0 + 8.0);
  95.    
  96.     secondHand_.bounds = CGRectMake(0.0, 0.0, 3.0, self.bounds.size.height / 2.0 + 8.0);
  97.     secondHand_.anchorPoint = CGPointMake(0.5, 0.8);
  98.     secondHand_.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  99.     secondHand_.lineWidth = 3.0;
  100.     secondHand_.strokeColor = [[UIColor redColor] CGColor];
  101.     secondHand_.path = path;
  102.     secondHand_.shadowOffset = CGSizeMake(0.0, 3.0);
  103.     secondHand_.shadowOpacity = 0.6;
  104.     secondHand_.lineCap = kCALineCapRound;
  105.    
  106.     [self.layer addSublayer:secondHand_];
  107.    
  108.     // minute hand
  109.     minuteHand_ = [CAShapeLayer layer];
  110.    
  111.     path = CGPathCreateMutable();
  112.     CGPathMoveToPoint(path, nil, 2.0, 0.0);
  113.     CGPathAddLineToPoint(path, nil, 2.0, self.bounds.size.height / 2.0);
  114.    
  115.     minuteHand_.bounds = CGRectMake(0.0, 0.0, 5.0, self.bounds.size.height / 2.0);
  116.     minuteHand_.anchorPoint = CGPointMake(0.5, 0.8);
  117.     minuteHand_.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  118.     minuteHand_.lineWidth = 5.0;
  119.     minuteHand_.strokeColor = [[UIColor blackColor] CGColor];
  120.     minuteHand_.path = path;
  121.     minuteHand_.shadowOffset = CGSizeMake(0.0, 3.0);
  122.     minuteHand_.shadowOpacity = 0.3;
  123.     minuteHand_.lineCap = kCALineCapRound;
  124.    
  125.     [self.layer addSublayer:minuteHand_];
  126.    
  127.     // hour hand
  128.     hourHand_ = [CAShapeLayer layer];
  129.    
  130.     path = CGPathCreateMutable();
  131.     CGPathMoveToPoint(path, nil, 3, 0);
  132.     CGPathAddLineToPoint(path, nil, 3.0, self.bounds.size.height / 3.0);
  133.    
  134.     hourHand_.bounds = CGRectMake(0.0, 0.0, 7.0, self.bounds.size.height / 3.0);
  135.     hourHand_.anchorPoint = CGPointMake(0.5, 0.8);
  136.     hourHand_.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  137.     hourHand_.lineWidth = 7.0;
  138.     hourHand_.strokeColor = [[UIColor blackColor] CGColor];
  139.     hourHand_.path = path;
  140.     hourHand_.shadowOffset = CGSizeMake(0.0, 3.0);
  141.     hourHand_.shadowOpacity = 0.3;
  142.     hourHand_.lineCap = kCALineCapRound;
  143.    
  144.     [self.layer addSublayer:hourHand_];
  145.    
  146.     // midpoint
  147.     CAShapeLayer *circle = [CAShapeLayer layer];
  148.    
  149.     path = CGPathCreateMutable();
  150.     CGPathAddEllipseInRect(path, nil, CGRectMake(0.0, 0.0, 11.0, 11.0));
  151.    
  152.     circle.fillColor = [[UIColor yellowColor] CGColor];
  153.     circle.bounds = CGRectMake(0.0, 0.0, 11.0, 11.0);
  154.     circle.path = path;
  155.     circle.shadowOpacity = 0.3;
  156.     circle.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
  157.     circle.shadowOffset = CGSizeMake(0.0, 5.0);
  158.    
  159.     [self.layer addSublayer:circle];
  160.    
  161.     [self updateHands];
  162. }
  163.  
  164. #pragma mark -
  165.  
  166. - (void)startUpdates {
  167.     updateTimer_ = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateHands) userInfo:nil repeats:YES];
  168. }
  169.  
  170. - (void)stopUpdates {
  171.     [updateTimer_ invalidate];
  172.     updateTimer_ = nil;
  173. }
  174.    
  175. - (void)updateHands {
  176.     NSDate *now = [NSDate date];
  177.     NSCalendar *cal = [NSCalendar currentCalendar];
  178.     NSDateComponents *comps = [cal components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:now];
  179.    
  180.     NSInteger minutesIntoDay = [comps hour] * 60 + [comps minute];
  181.     float percentageMinutesIntoDay = minutesIntoDay / (12.0 * 60.0);
  182.     float percentageMinutesIntoHour = (float)[comps minute] / 60.0;
  183.     float percentageSecondsIntoMinute = (float)[comps second] / 60.0;
  184.    
  185.     secondHand_.transform = CATransform3DMakeRotation((M_PI * 2) * percentageSecondsIntoMinute, 0, 0, 1);
  186.     minuteHand_.transform = CATransform3DMakeRotation((M_PI * 2) * percentageMinutesIntoHour, 0, 0, 1);
  187.     hourHand_.transform = CATransform3DMakeRotation((M_PI * 2) * percentageMinutesIntoDay, 0, 0, 1);
  188. }
  189.  
  190. @end
  191.  
  192.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement