iOS开发之手动绘制时钟模拟器

来源:互联网 发布:如何在阿里云建网站 编辑:程序博客网 时间:2024/04/30 07:41


用系统提供的corez2D框架,将我们现实生活中的钟表在xode中画出来,并显示在应用程序上,钟表上包括表盘、时针、分针、秒针,当我们运行程序的时候,程序将根据系统当前时间去设置该钟表的时间,当点击暂停按钮后,时间模拟器将暂停,当点击开始按钮后不会从你停止的那个时间转动,会跳到系统当前时间再转动。当系统时间发生改变的时候,将获取当前系统的时间,计算出指针的旋转角度,并做出相应旋转,从而达到现实生活中指针转动的效果。


实现原理:

1.自定义clock,通过外面将一些属性值传进来,通过这些值设置表盘的颜色,时针、分针、秒针的颜色

@property(nonatomic,strong)UIColor *clockTintColor;@property(nonatomic,assign)CGFloat clockBorderWidth;@property(nonatomic,strong)UIColor *clockBorderColor; @property(nonatomic,strong)UIColor *hourHandColor;@property(nonatomic,assign)CGFloat hourHandWidth;@property(nonatomic,strong)UIColor *minuteHandColor; @property(nonatomic,assign)CGFloat minuteHandWidth;@property (nonatomic, strong) UIColor *secondHandColor;         @property (nonatomic, assign) CGFloat secondHandWidth;          @property (nonatomic, strong) NSDictionary *momentAttribute;    @property (nonatomic, strong) NSArray *momentList;              @property (nonatomic, strong) UIColor *centerPointColor;        @property (nonatomic, assign) CGFloat centerPointRadius;   

2.获取上下文对象,通过外部给表盘设置的大小,计算表盘的半径,并将表盘的边框和背景绘制

    CGContextRef context = UIGraphicsGetCurrentContext();            //绘制表盘边框和背景色    CGContextSetStrokeColorWithColor(context, _clockBorderColor.CGColor);    CGContextSetFillColorWithColor(context, _clockTintColor.CGColor);    CGContextSetLineWidth(context, _clockBorderWidth);        _radius = (self.frame.size.width < self.frame.size.height)?self.frame.size.width/2.f : self.frame.size.height/2.f;    _radius = _radius - _clockBorderWidth;    CGContextAddArc(context, CGRectGetWidth(self.frame)/2.f, CGRectGetHeight(self.frame)/2.f, _radius, 0.f, 2*M_PI, 0.f);    CGContextDrawPath(context, kCGPathFillStroke);

效果图:


3.创建一个队列,创建定时器,将定时器加入队列中使用 dispatch_source_set_timer函数设置定时器信息,因为block中可能 会出现循环引用,所以使用weak关键字来修饰,可以避免循环引用

//创建一个GCD队列    dispatch_queue_t queue = dispatch_queue_create("Clock Timer Run Queue", 0);           _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);        //使用 dispatch_source_set_timer 函数设置定时器信息    dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC, 0);    __weak Clock *weakSelf = self;    dispatch_source_set_event_handler(_timer, ^{       dispatch_sync(dispatch_get_main_queue(), ^{                     __strong Clock *strongSelf = weakSelf;           [strongSelf updateClock];       });//回到主线程,刷新            });

4.计算表盘刻度的位置,并设置表盘文字的属性,将表盘刻度绘制在表盘上

for(int i = 0;i < 12;i++){                NSString *momentStr = _momentList[i];        CGRect fontRect = [momentStr boundingRectWithSize:CGSizeMake(_radius, MAXFLOAT) options:0 attributes:_momentAttribute context:nil];                CGFloat angle = i * 30;        CGFloat x = CGRectGetWidth(self.frame)/2.f + smallerRadius * sin(angle*M_PI/180.f)-fontRect.size.width/2.f;        CGFloat y = CGRectGetHeight(self.frame)/2.f - smallerRadius * cos(angle*M_PI/180.f)-fontRect.size.height/2.f;        [pointList addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]];    }
<p><span style="background-color: rgb(240, 240, 240);">  //绘制表盘刻度</span></p><pre name="code" class="html">    for (int i = 0; i < _momentList.count; i++) {        NSString *momentStr = _momentList[i];        CGPoint momentPoint = [momentPointList[i] CGPointValue];        [momentStr drawAtPoint:momentPoint withAttributes:_momentAttribute];    }    //CGContextRelease(context);    //绘制表盘指针


效果图:


5.通过贝塞尔曲线绘制出时针、分针、秒针和中心点,并将他们生成图片,通过生成的图片,计算出指针的位置,并将图片绘制到表盘上,因为时针、分针、秒针实现原理大致相同,代码只例出时针部分,


-(UIImage *)drawHourHand{    //通过外部传进来的时针宽度和半径,设置时针的尺寸    CGSize hourHandSize = CGSizeMake(_hourHandWidth, _radius*2.5f/5.f);    UIGraphicsBeginImageContextWithOptions(hourHandSize, NO, [UIScreen mainScreen].scale);    UIBezierPath *bPath = [UIBezierPath bezierPathWithRect:CGRectMake(0.f, 0.f, hourHandSize.width, hourHandSize.height)];    [_hourHandColor setFill];    [bPath fill];    //将图片通过贝塞尔曲线绘制出来    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    return image;}

//绘制中心圆点,并生成图片-(UIImage *)drawCenterPoint{        CGSize centerPointSize = CGSizeMake(2*_centerPointRadius, 2*_centerPointRadius);    UIGraphicsBeginImageContextWithOptions(centerPointSize, NO, [UIScreen mainScreen].scale);    UIBezierPath *bPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.f, 0.f, centerPointSize.width, centerPointSize.height) cornerRadius:_centerPointRadius];    [_centerPointColor setFill];    [bPath fill];    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    return image;}
<pre name="code" class="objc">//通过返回的时针图片,计算时针在表盘中的位置,并将其绘制在表盘上    UIImage *hourHandImage = [self drawHourHand];    CGSize hourHandSize = hourHandImage.size;    _hourHand = [[UIImageView alloc] initWithImage:hourHandImage];    _hourHand.contentMode = UIViewContentModeTop;    _hourHand.frame = CGRectMake(CGRectGetWidth(self.frame)/2.f - hourHandSize.width, CGRectGetHeight(self.frame)/2.f-hourHandSize.height,hourHandSize.width, hourHandSize.height*2);    _hourHand.layer.shouldRasterize = YES;    [self addSubview:_hourHand];


效果图:


6.控制定时器的开始、暂停

//因为时针是由定时器控制的,所以当我们暂停或开始时,只需控制定时器即可-(void)start{        dispatch_resume(_timer);}-(void)stop{        dispatch_suspend(_timer);}


7即时刷新,通过系统当前时间的时、分、秒得出关系然后计算出时针、分针、秒针的在表盘的位置,当时间发生改变时,重新计算出指针的位置

    NSDate *date = [NSDate date];    NSDateComponents *dateComponents = [_calendar components:NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:date];    CGFloat hourAngle = 0.5f * (60.f * dateComponents.hour + dateComponents.minute);    CGFloat minuteAngle = 6.f *dateComponents.minute;    CGFloat secondAngle = 6.f *dateComponents.second;    hourAngle = hourAngle > 360.f ? hourAngle - 360.f :hourAngle;    secondAngle = secondAngle > 360.f?hourAngle-360.f:secondAngle;    [UIView animateWithDuration:0.075 animations:^{               _hourHand.transform = CGAffineTransformMakeRotation(hourAngle * (M_PI/180.f));        _minuteHand.transform = CGAffineTransformMakeRotation(minuteAngle *(M_PI/180.f));        _secondHand.transform = CGAffineTransformMakeRotation(secondAngle*(M_PI/180.f));    }];


8、在程序加载的时候创建一个clock对象,实例化该对象,并设置该表盘指针的宽度、颜色和表盘刻度文字的属性

-(void)setupBigClock{        CGFloat diameter = 300.f;    CGFloat leftPadding = (CGRectGetWidth(self.view.frame)-diameter)/2.f;    clock1 = [[Clock alloc] init];    clock1.frame = CGRectMake(leftPadding, 200.f, diameter, diameter);    [self.view addSubview:clock1];    [clock1 start];        clock1.clockBorderWidth = 2.f;    clock1.clockBorderColor = [UIColor magentaColor];        clock1.hourHandColor = [UIColor blueColor];    clock1.hourHandWidth = 7.f,        clock1.minuteHandColor = [UIColor greenColor];    clock1.minuteHandWidth = 5.f;        clock1.secondHandColor = [UIColor redColor];    clock1.secondHandWidth = 3.f;        clock1.centerPointColor = [UIColor purpleColor];    clock1.centerPointRadius = 10.f;    clock1.momentAttribute = @{NSFontAttributeName : [UIFont fontWithName:@"Noteworthy" size:30],                               NSForegroundColorAttributeName : [UIColor yellowColor]};}

运行效果图:

       

0 0
原创粉丝点击