It’s kind of nice to be able to dynamically draw little ‘clock’ time icons. This function returns a UIImage of 30×30 pixels containing such an image:
static inline float radians(double degrees) { return (degrees * M_PI) / 180; } - (UIImage *)drawTime:(NSNumber *)time { UIImage *image; CGRect rect = CGRectMake(0,0,30,30); UIGraphicsBeginImageContext(rect.size); CGContextRef context = UIGraphicsGetCurrentContext(); // Calculate end angle in radians according to time..... e.g. 60mins == 360o == 360*M_PI/180 CGFloat endAngle = radians((360/60)*[time doubleValue]); // Set colors CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); CGContextSetFillColorWithColor(context, [[UIColor grayColor] CGColor]); // Set Pen width. CGContextSetLineWidth(context, 1); // Draw outer circle CGContextStrokeEllipseInRect(context, CGRectMake(1, 1, 28, 28)); // Set rect to top left of where we want next circle CGContextStrokeEllipseInRect(context, CGRectMake(4, 4, 22, 22)); // Draw segment as grey CGContextMoveToPoint(context, 15.0f, 15.0f); CGContextBeginPath(context); // Draw radius out so we end up with a segment drawn and NOT a chord CGContextAddLineToPoint(context, 15, 5); // Draw arc, note documentation states final argument is 1 for Clockwise and 0 for CCW. // However, iOS inverts the Y axis so 0 for CCW becomes CW. OF COURSE! CGContextAddArc(context, 15, 15, 10, 0, endAngle, 0); // Add line back to middle CGContextAddLineToPoint(context, 15, 15); CGContextClosePath(context); CGContextFillPath(context); // Gimme ma image. image = UIGraphicsGetImageFromCurrentImageContext(); /* Due more core graphics weirdness note from the documentation that: startAngle The angle to the starting point of the arc, measured in radians from the positive x-axis. Thus the resulting image will need a -90o transformation to look like a clock. E.g. 0 is North Simple way is to apply an affine rotation transformation to the view as it will rotate from the centre point. The CG Rotate will perform from the origin so you would need to translate, rotate, translate seeing as The CG instance has it's Y axis inversed. What crack smoking @!$% came up with this co-ordinate system? This isn't 3D graphics people. It's 2D stick to one co ordinate system not 2! */ // Close context UIGraphicsEndImageContext(); return image; }
Input value must be between 0 and 60 minutes. Also the result image will need a 90degree CCW transform applied, due to co-ordinate changes between Core Graphics and main iOS you may find, depending on where one applies it, that it becomes a 90 degree CW rotation. Ho hum. For values over 60 minutes I would recommend a helper function to draw several clocks alongside one another and return that resulting image.
UPDATE:
This entry continues this tale…
One Response to Drawing little clock icons dynamically.