利用计时器数字简单绘制个小闹钟

2,913 阅读4分钟

废话开篇:利用计时器数字简单绘制个小闹钟

绘制数字: # 代码绘制计时器数字

数字效果:#给代码绘制计时器数字加个效果

一、效果展示

屏幕录制2022-11-09 下午2.36.10.gif

这里面很简单,就是把之前的计时器数字在 viewdraw 方法里绘制了一些图形,再把 NumberView 视图展示到对应的位置。

这里面除了时间显示 NumberView 以外,均为贝塞尔曲线绘制填充完成。

二、代码

#import "AlarmView.h"
#import "NumberView.h"

//定时器定时任务
typedef void(^ReadCurrenTimeBlock)(void); 

@interface AlarmView()
//上面显示的距离
@property(nonatomic,assign) float topDistance;
//倒角半径
@property(nonatomic,assign) float radius;
//时钟展示区域
@property(nonatomic,assign) CGRect alarmFrame;
//基础展示视图
@property(nonatomic,strong) UIView * contentView;
//定时器
@property(nonatomic,strong) NSTimer * timer;
//定时器定时任务
@property(nonatomic,copy) ReadCurrenTimeBlock readCurrenTimeBlock;
@end

@implementation AlarmView

- (instancetype)initWithFrame:(CGRect)frame topDistance:(float)topDistance
{
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor clearColor];
        self.topDistance = topDistance;
        self.radius = 30;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self createNumberView];
            [self startTimer];
        });
    }
    return self;
}
  
- (void)drawRect:(CGRect)rect
{
    float sep = 1;
    [self drawTopControl:CGRectMake(0, 0, rect.size.width, self.topDistance + self.radius) radius:20];
    [self drawCustomRect:CGRectMake(sep, self.topDistance + sep, rect.size.width - sep * 2, rect.size.height - self.topDistance - sep * 2) radius:self.radius color:[UIColor whiteColor]];
    sep += 25;
    [self drawCustomRect:CGRectMake(sep, self.topDistance + sep, rect.size.width - sep * 2, rect.size.height - self.topDistance - sep * 2) radius:15 color:[UIColor colorWithRed:235 / 255.0 green:235 / 255.0 blue:235 / 255.0 alpha:1]];
    sep += 15;
    self.alarmFrame = CGRectMake(sep, self.topDistance + sep, rect.size.width - sep * 2, rect.size.height - self.topDistance - sep * 2);
    [self drawMainScreen:self.alarmFrame radius:10];
}


#pragma mark -绘制顶部
- (void)drawTopControl:(CGRect)rect radius:(**float**)radius
{
    [[UIColor lightGrayColor] set];
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(CGRectGetMinX(rect) + self.radius, CGRectGetMaxY(rect)) radius:self.radius startAngle:M_PI endAngle:M_PI_2 * 3 clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMaxX(rect) - self.radius, CGRectGetMaxY(rect) - self.radius)];
    [path addArcWithCenter:CGPointMake(CGRectGetMaxX(rect) - self.radius, CGRectGetMaxY(rect)) radius:self.radius startAngle:M_PI_2 * 3 endAngle:0 clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMaxX(rect) - radius,CGRectGetMinY(rect) + radius)];
    [path addArcWithCenter:CGPointMake(CGRectGetMaxX(rect) - radius * 2, CGRectGetMinY(rect) + radius) radius:radius startAngle:M_PI * 2 - M_PI / 6.0  endAngle:M_PI_2 * 3 clockwise:NO];
    [path addLineToPoint:CGPointMake(CGRectGetMinX(rect) + radius * 2,CGRectGetMinY(rect))];
    [path addArcWithCenter:CGPointMake(CGRectGetMinX(rect) + radius * 2, CGRectGetMinY(rect) + radius) radius:radius startAngle:M_PI_2 * 3 endAngle:M_PI + M_PI / 6.0 clockwise:NO];
    [path addLineToPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect))];
    [path fill];
}

#pragma mark - 绘制边框
- (void)drawCustomRect:(CGRect)rect radius:(float)radius color:(UIColor *)color
{
    [color set];
    UIBezierPath *path = [UIBezierPath bezierPath];
    //左上
    [path addArcWithCenter:CGPointMake(CGRectGetMinX(rect) + radius, CGRectGetMinY(rect) + radius) radius:radius startAngle:M_PI endAngle:M_PI_2 * 3 clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect))];
    //右上
    [path addArcWithCenter:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect) + radius) radius:radius startAngle:M_PI_2 * 3 endAngle:0 clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect) - radius)];
    //右下
    [path addArcWithCenter:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMaxY(rect) - radius) radius:radius startAngle:0 endAngle:M_PI_2  clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect))];
    //左下
    [path addArcWithCenter:CGPointMake(CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect) - radius) radius:radius startAngle:M_PI_2 endAngle:M_PI  clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect) + radius)];
    [path fill];
    color = [UIColor darkGrayColor];
    [color set];
    path.lineWidth = 1;
    [path stroke];
}

#pragma mark - 绘制渐变色显示屏
- (void)drawMainScreen:(CGRect)rect radius:(**float**)radius
{
    UIBezierPath *path = [UIBezierPath bezierPath];
    //左上
    [path addArcWithCenter:CGPointMake(CGRectGetMinX(rect) + radius, CGRectGetMinY(rect) + radius) radius:radius startAngle:M_PI endAngle:M_PI_2 * 3 clockwise:**YES**];
    [path addLineToPoint:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect))];
    //右上
    [path addArcWithCenter:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect) + radius) radius:radius startAngle:M_PI_2 * 3 endAngle:0 clockwise:**YES**];
    [path addLineToPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect) - radius)];
    //右下
    [path addArcWithCenter:CGPointMake(CGRectGetMaxX(rect) - radius, CGRectGetMaxY(rect) - radius) radius:radius startAngle:0 endAngle:M_PI_2  clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect))];
    //左下
    [path addArcWithCenter:CGPointMake(CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect) - radius) radius:radius startAngle:M_PI_2 endAngle:M_PI  clockwise:YES];
    [path addLineToPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect) + radius)];
    //渐变色主屏幕
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGFloat locations[] = { 0.0,0.2,0.8, 1.0 };
    NSArray *colors = @[( __bridge id) [UIColor colorWithRed:159 / 255.0 green:195 / 255.0 blue:248 / 255.0 alpha:1].CGColor, ( __bridge id) [UIColor colorWithRed:226 / 255.0 green:253 / 255.0 blue:254 / 255.0 alpha:1].CGColor,( __bridge id) [UIColor colorWithRed:226 / 255.0 green:253 / 255.0 blue:254 / 255.0 alpha:1].CGColor,( __bridge id) [UIColor colorWithRed:159 / 255.0 green:195 / 255.0 blue:248 / 255.0 alpha:1].CGColor];
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, ( __bridge CFArrayRef) colors, locations);
    CGRect pathRect = CGPathGetBoundingBox(path.CGPath);
    CGPoint startPoint = CGPointMake(CGRectGetMinX(pathRect), CGRectGetMidY(pathRect));
    CGPoint endPoint = CGPointMake(CGRectGetMaxX(pathRect), CGRectGetMidY(pathRect));
    CGContextSaveGState(context);
    CGContextAddPath(context, path.CGPath);
    CGContextClip(context);
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
    CGContextRestoreGState(context);
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
    [self.layer addSublayer:imgView.layer];
}

#pragma mark - 创建秒数视图
- (void)createNumberView
{
    self.contentView = [[UIView alloc] initWithFrame:self.alarmFrame];
    self.contentView.backgroundColor = [UIColor clearColor];
    [self addSubview:self.contentView];
    float height = 45;
    float flashingWidth = 30;
    //小时
    NumberView * hourNumberView = [[NumberView alloc] initWithFrame:CGRectMake(0, (self.contentView.frame.size.height - height) / 2.0, (self.contentView.frame.size.width - flashingWidth) / 2.0, height) maxDigits:2 numberAlignmentType:(NumberAlignmentRight) numberColor:[UIColor blackColor] numberChangeAnimation:(NumberChangeAnimationFade)];
    hourNumberView.backgroundColor = [UIColor clearColor];
    [self.contentView addSubview:hourNumberView];
    //中间闪烁点
    UIView * flashingView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(hourNumberView.frame), 0, flashingWidth, self.contentView.frame.size.height)];
    [self.contentView addSubview:flashingView];
    //闪点宽度
    float flashingCircleWidth = 6;
    //闪点间隔
    float flashingCircleSep = 10;
    CALayer * circleTopLayer = [[CALayer alloc] init];
    circleTopLayer.frame = CGRectMake((flashingView.frame.size.width - flashingCircleWidth) / 2.0, (flashingView.frame.size.height - (flashingCircleWidth * 2 + flashingCircleSep)) / 2.0, flashingCircleWidth, flashingCircleWidth);
    circleTopLayer.backgroundColor = [UIColor blackColor].CGColor;
    circleTopLayer.cornerRadius = flashingCircleWidth / 2.0;
    [flashingView.layer addSublayer:circleTopLayer];
    CALayer * circleDownLayer = [[CALayer alloc] init];
    circleDownLayer.frame = CGRectMake((flashingView.frame.size.width - flashingCircleWidth) / 2.0, CGRectGetMaxY(circleTopLayer.frame) + flashingCircleSep, flashingCircleWidth, flashingCircleWidth);
    circleDownLayer.backgroundColor = [UIColor blackColor].CGColor;
    circleDownLayer.cornerRadius = flashingCircleWidth / 2.0;
    [flashingView.layer addSublayer:circleDownLayer];
    //分钟
    NumberView * minutesNumberView = [[NumberView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(flashingView.frame), (self.contentView.frame.size.height - height) / 2.0, (self.contentView.frame.size.width - flashingWidth) / 2.0, height) maxDigits:2 numberAlignmentType:(NumberAlignmentLeft) numberColor:[UIColor blackColor] numberChangeAnimation:(NumberChangeAnimationFade)];
    minutesNumberView.backgroundColor = [UIColor clearColor];
    [self.contentView addSubview:minutesNumberView];

    //时间读取回调
    self.readCurrenTimeBlock = ^{
        //开始整理时间
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"YYYY-MM-dd"];
        NSDate *date = [NSDate date];
        NSCalendar *calendar = [NSCalendar currentCalendar];
        NSDateComponents *components = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:date];
        NSInteger hour = [components hour];
        NSInteger minute = [components minute];
        hourNumberView.currentNum = hour;
        minutesNumberView.currentNum = minute;
        //闪烁
        flashingView.hidden = NO;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            flashingView.hidden = YES;
        });
    };
}
  
#pragma mark - 开启定时器
- (void)startTimer
{
    __weak typeof(self) weakSelf = self;
    if ( @available(iOS 10.0, *)) {
        weakSelf.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            if(weakSelf.readCurrenTimeBlock){
                weakSelf.readCurrenTimeBlock();
            }
        }];
        [weakSelf.timer fire];
    }
}

@end

三、总结与思考

没啥复杂的内容,很长时间不写iOS了,找找以前的感觉,代码拙劣,大神勿笑。[抱拳][抱拳][抱拳]