美文网首页
iOS不到100行代码实现时钟功能

iOS不到100行代码实现时钟功能

作者: QuakOrigin | 来源:发表于2018-06-29 14:28 被阅读0次

    利用 UIViewtransform 函数 CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle)
    该方法需要传入一个角度值的参数,所以需要实时获取当前时间的时分秒数值,这里参考用 NSCalendar 日历类来获取相关数值,然后还需要一个 UIView 的实例变量,当然如果想要秒针动起来,NSTimer 也是必不可少的。
    当然,首先需要几张图片。时钟指针图片来自 阿里巴巴矢量图库, 表盘来自百度。

    clock_bg.png
    pt_hour.png
    pt_minute.png
    pt_second.png

    直接上代码,首先需要背景表盘与三根时钟指针

    @interface LayerClockViewController ()
    
    @property (nonatomic, strong) UIImageView *imgClock;
    @property (nonatomic, strong) UIImageView *hourHand;
    @property (nonatomic, strong) UIImageView *minuteHand;
    @property (nonatomic, strong) UIImageView *secondHand;
    
    @end
    

    这里偷懒了,imgClock 做了懒加载,指针一起处理了。

    - (UIImageView *)imgClock
    {
        if(!_imgClock) {
            
            CGPoint point = self.view.center;
            
            _imgClock = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 250, 250)];
            _imgClock.center = point;
            [self.view addSubview:_imgClock];
            
            _secondHand = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
            _secondHand.center = point;
            _secondHand.layer.anchorPoint = CGPointMake(0.5, 0.9);
            [self.view addSubview:_secondHand];
            
            _minuteHand = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
            _minuteHand.center = point;
            _minuteHand.layer.anchorPoint = CGPointMake(0.5, 0.9);
            [self.view addSubview:_minuteHand];
            
            _hourHand = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
            _hourHand.center = point;
            _hourHand.layer.anchorPoint = CGPointMake(0.5, 0.8);
            [self.view addSubview:_hourHand];
        }
        return _imgClock;
    }
    

    注意属性 anchorPoint 的作用,为视图添加锚点,不加这行代码的话,转起来会比较酸爽。
    然后是钟表视图添加图片

    - (void)drawClock
    {
        CALayer *layerClock = [[CALayer alloc] init];
        layerClock.frame = CGRectMake(0, 0, self.imgClock.frame.size.width, self.imgClock.frame.size.height);
        layerClock.contents = (__bridge id)[UIImage imageNamed:@"clock_bg"].CGImage;
        [self.imgClock.layer addSublayer:layerClock];
        
        CALayer *layerHour = [[CALayer alloc] init];
        layerHour.frame = CGRectMake(0, 0, 100, 100);
        layerHour.contents = (__bridge id)[UIImage imageNamed:@"pt_hour"].CGImage;
        [self.hourHand.layer addSublayer:layerHour];
    
        CALayer *layerMinute = [[CALayer alloc] init];
        layerMinute.frame = CGRectMake(0, 0, 100, 100);
        layerMinute.contents = (__bridge id)[UIImage imageNamed:@"pt_mimute"].CGImage;
        [self.minuteHand.layer addSublayer:layerMinute];
    
        CALayer *layerSecond = [[CALayer alloc] init];
        layerSecond.frame = CGRectMake(0, 0, 100, 100);
        layerSecond.contents = (__bridge id)[UIImage imageNamed:@"pt_second"].CGImage;
        [self.secondHand.layer addSublayer:layerSecond];
    }
    

    最后就是角度的获取了

    - (void)timeFire
    {
        NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierChinese];
        NSCalendarUnit unit = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
        NSDateComponents *components = [calendar components:unit fromDate:[NSDate new]];
        
        CGFloat hourAngal = ((CGFloat)labs(components.hour-12)/12)*2*M_PI; //先转成12小时制
        CGFloat minuteAngal = ((CGFloat)components.minute/60)*2*M_PI;
        CGFloat secondAngal = ((CGFloat)components.second/60)*2*M_PI;
        
        self.hourHand.transform = CGAffineTransformMakeRotation(hourAngal);
        self.minuteHand.transform = CGAffineTransformMakeRotation(minuteAngal);
        self.secondHand.transform = CGAffineTransformMakeRotation(secondAngal);
    }
    

    这里用 components.hour 获取当前小时,是24小时制的,看了下 NSDateComponents 类,没有找到设置时间格式为12小时的属性,暂时只能这么处理下。(若有好的方法请不吝赐教)

    最后愉快的调用就好了

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self drawClock];
        [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeFire) userInfo:nil repeats:YES];
        [self timeFire]; //手动调用一次的主要目的是首次显示当前的时钟,不然会先显示12点,1秒后转到正确时间。
    }
    

    为了保证界面的流畅性,需要先手动调用一下 timeFire

    看看效果:


    clock.gif

    效果还行,仔细看时针指的位置是不对的,按理说应该在靠近6点的位置才对,核对下代码后发现

    CGFloat hourAngal = ((CGFloat)labs(components.hour-12)/12)*2*M_PI;
    

    时针的角度只是处理了小时,没有把分钟的算进去,同理分钟的指针也没有把秒计算在内。
    把分钟加进去

    CGFloat hourAngal = ((CGFloat)fabs((components.hour-12)+((CGFloat)components.minute/60))/12)*2*M_PI;
    

    效果就比较理想了


    clock_new.gif

    感谢爱抽烟的芭比提供的 iPhoneSimulator的录屏代码

    xcrun simctl io booted recordVideo filename.mov
    

    以及KFAaron
    提供的 .mov.gif 的方法,可惜自己在用 brew 安装 ffmpeg 的时候一直报错,texi2html 下载地址无法访问,开关 vpn 都不好使,只好作罢

    ==> Installing dependencies for ffmpeg: texi2html, yasm, x264, lame, xvid
    ==> Installing ffmpeg dependency: texi2html
    ==> Downloading http://download.savannah.gnu.org/releases/texi2html/texi2html-5.
    ==> Downloading from http://ftp.yzu.edu.tw/nongnu/texi2html/texi2html-5.0.tar.gz
    
    curl: (7) Failed to connect to ftp.yzu.edu.tw port 80: Operation timed out
    Error: Failed to download resource "texi2html"
    Download failed: http://ftp.yzu.edu.tw/nongnu/texi2html/texi2html-5.0.tar.gz
    

    最后只好放弃,用了 GIF Brewery 3 墙裂推荐,功能很强大,使用也很方便。

    参考自 iOS Core Animation: Advanced Techniques

    相关文章

      网友评论

          本文标题:iOS不到100行代码实现时钟功能

          本文链接:https://www.haomeiwen.com/subject/aabgyftx.html