Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here's how I do it - I use the face center and the angle to compute the x,y position of the endpoints of the hands, drawing is simple from there. Here's a complete clock face class. It's a subclass of UIView. Set it's time property every second and it works like a charm...</p> <pre><code>// // ClockFace.h // #import &lt;UIKit/UIKit.h&gt; @interface ClockFace : UIView @property (strong,nonatomic) NSDate *time; @end // ClockFace.m #import "ClockFace.h" @interface ClockFace () @property(assign,nonatomic) CGPoint boundsCenter; @property(assign,nonatomic) NSInteger seconds; @property(assign,nonatomic) NSInteger minutes; @property(assign,nonatomic) NSInteger hours; @end @implementation ClockFace @synthesize time=_time; @synthesize boundsCenter=_boundsCenter; - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { _boundsCenter = CGPointMake(self.bounds.size.width/2.0, self.bounds.size.height/2.0); } return self; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code _boundsCenter = CGPointMake(self.bounds.size.width/2.0, self.bounds.size.height/2.0); } return self; } - (CGPoint)secondsHandPosition { float secondsAsRadians = (float)self.seconds / 60.0 * 2.0 * M_PI - M_PI_2; float handRadius = self.frame.size.width / 2.4; return CGPointMake(handRadius*cosf(secondsAsRadians)+self.boundsCenter.x, handRadius*sinf(secondsAsRadians)+self.boundsCenter.y); } - (CGPoint)minutesHandPosition { float minutesAsRadians = (float)self.minutes / 60.0 * 2.0 * M_PI - M_PI_2; float handRadius = self.frame.size.width / 2.2; return CGPointMake(handRadius*cosf(minutesAsRadians)+self.boundsCenter.x, handRadius*sinf(minutesAsRadians)+self.boundsCenter.y); } - (CGPoint)hoursHandPosition { float hoursAsRadians = (float)self.hours / 12.0 * 2.0 * M_PI - M_PI_2; float handRadius = self.frame.size.width / 3.8; return CGPointMake(handRadius*cosf(hoursAsRadians)+self.boundsCenter.x, handRadius*sinf(hoursAsRadians)+self.boundsCenter.y); } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGFloat zClear[4] = {1.0,1.0,1.0,0.0}; CGContextSetFillColor(context, zClear); CGContextFillRect(context, rect); CGRect face = CGRectInset(rect, 1.0, 1.0); CGContextSetLineWidth(context, 1.0); CGContextAddEllipseInRect(context, face); CGContextStrokePath(context); CGRect center = CGRectMake(self.boundsCenter.x-2.0, self.boundsCenter.y-2.0, 4.0, 4.0); CGContextAddEllipseInRect(context, center); CGContextStrokePath(context); CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f}; CGPoint secondsHandPosition = [self secondsHandPosition]; CGContextSetStrokeColor(context, red); CGContextBeginPath(context); CGContextMoveToPoint(context, self.boundsCenter.x, self.boundsCenter.y); CGContextAddLineToPoint(context, secondsHandPosition.x, secondsHandPosition.y); CGContextStrokePath(context); CGFloat black[4] = {0.0f, 0.0f, 0.0f, 1.0f}; CGPoint minutesHandPosition = [self minutesHandPosition]; CGContextSetStrokeColor(context, black); CGContextBeginPath(context); CGContextMoveToPoint(context, self.boundsCenter.x, self.boundsCenter.y); CGContextAddLineToPoint(context, minutesHandPosition.x, minutesHandPosition.y); CGContextStrokePath(context); CGPoint hoursHandPosition = [self hoursHandPosition]; CGContextSetStrokeColor(context, black); CGContextBeginPath(context); CGContextMoveToPoint(context, self.boundsCenter.x, self.boundsCenter.y); CGContextAddLineToPoint(context, hoursHandPosition.x, hoursHandPosition.y); CGContextStrokePath(context); } - (void)setTime:(NSDate *)time { _time = time; static NSCalendar *gregorian; if (!gregorian) gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents *weekdayComponents = [gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:time]; self.hours = [weekdayComponents hour]; if (self.hours &gt; 12) self.hours -= 12; self.minutes = [weekdayComponents minute]; self.seconds = [weekdayComponents second]; [self setNeedsDisplay]; } @end </code></pre> <p>To use this in a view controller, create a property:</p> <pre><code>#import "ClockFace.h" // ... @property(strong, non atomic) ClockFace *clockFace; </code></pre> <p>In view did load (or in storyboard if you know how to add custom views):</p> <pre><code>self.clockFace = [[ClockFace alloc] initWithFrame:CGRectMake(10, 10, 300, 300)]; </code></pre> <p>Whenever you want the clock to run, setup a timer:</p> <pre><code>[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFired:) userInfo:nil repeats:NO]; </code></pre> <p>When the timer fires, tell the clock what time it is:</p> <pre><code>- (void)timerFired:(NSTimer *)timer { self.clockFace.time = [NSDate date]; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload