iOS动画(一):时钟动画(Swift)

iOS 241 2017-11-07 22:56

参考:

  • iOS动画系列之一:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画(上)
  • iOS动画系列之二:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画。包含了OC和Swift两种源代码(下)
iOS动画(一):时钟动画(Swift)-JEESNS

一、直接做动画

  • 新建项目clock
  • 加载表盘图片。
    iOS动画(一):时钟动画(Swift)-JEESNS

    viewDidLoad中添加:
          let dialLayer = CALayer()
          dialLayer.bounds = CGRect(x: 0, y: 0, width: 150, height: 150)
          dialLayer.position = self.view.center
          dialLayer.contents = UIImage(named: "clock")?.cgImage
          
          view.layer.addSublayer(dialLayer)
    
  • 懒加载秒针、分针、时针视图。懒加载机制是Swift中一种存储属性:延迟存储属性,具体可擦看 以撸代码的形式学习Swift-10:Properties
      // 秒针
      lazy var secondHandView: UIView = {
          let secondHandView = UIView()
          secondHandView.backgroundColor = UIColor.red
          secondHandView.bounds = CGRect(x: 0, y: 0, width: 1, height: 60)
          
          secondHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
    
          return secondHandView
      }()
      
      // 分针
      lazy var minuteHandView: UIView = {
          let minuteHandView = UIView()
          minuteHandView.backgroundColor = UIColor.darkGray
          minuteHandView.bounds = CGRect(x: 0, y: 0, width: 3, height: 60)
          
          minuteHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
          
          return minuteHandView
      }()
      
      // 时针
      lazy var hourHandView: UIView = {
          let hourHandView = UIView()
          hourHandView.backgroundColor = UIColor.darkGray
          hourHandView.bounds = CGRect(x: 0, y: 0, width: 3, height: 45)
          
          hourHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
          
          return hourHandView
      }()
    
  • 把秒针、分针、时针添加到view中。在viewDidLoad中添加:
          secondHandView.center = view.center
          self.view.addSubview(secondHandView)
          minuteHandView.center = view.center
          self.view.addSubview(minuteHandView)
          hourHandView.center = view.center
          self.view.addSubview(hourHandView)
    
  • 创建CADisplayLink,并将其添加到主线程中。在viewDidLoad中添加:
          let link = CADisplayLink(target: self, selector: #selector(ViewController.clockRunning))
          link.add(to: RunLoop.main, forMode: .defaultRunLoopMode)
    
  • 添加方法clockRunning:
      func clockRunning() {
          let tZone = TimeZone.current
          var calendar = Calendar.current
          let currentDate = Date()
          calendar.timeZone = tZone
          
          let currentTime = calendar.dateComponents([Calendar.Component.hour, Calendar.Component.minute, Calendar.Component.second], from: currentDate)
          
          // 根据当前秒、分、时数分别计算秒针、分针、时针偏转弧度
          let secondAngle = CGFloat ( Double(currentTime.second!) * (Double.pi * 2.0 / 60) )
          secondHandView.transform = CGAffineTransform(rotationAngle: secondAngle)
          
          let minuteAngle = CGFloat ( Double(currentTime.minute!) * (Double.pi * 2.0 / 60) )
          minuteHandView.transform = CGAffineTransform(rotationAngle: minuteAngle)
          
          let hourAngle = CGFloat ( Double(currentTime.hour!) * (Double.pi * 2.0 / 12) )
          hourHandView.transform = CGAffineTransform(rotationAngle: hourAngle)
      }
    

现在就完成了文章开头的效果。

二、代码说明

  1. 关于anchorPoint(锚点)
    如果注释掉分针和时针视图,并且关掉动画效果和锚点设置:
//        secondHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
//        minuteHandView.center = view.center
//        self.view.addSubview(minuteHandView)
//        hourHandView.center = view.center
//        self.view.addSubview(hourHandView)
        
        // 创建CADisplayLink,并将其添加到主线程中
//        let link = CADisplayLink(target: self, selector: #selector(ViewController.clockRunning))
//        link.add(to: RunLoop.main, forMode: .defaultRunLoopMode)
iOS动画(一):时钟动画(Swift)-JEESNS

加上secondHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)后:

iOS动画(一):时钟动画(Swift)-JEESNS

anchorPoint的官方描述:

Defines the anchor point of the layer's bounds rectangle. Animatable.
You specify the value for this property using the unit coordinate space. The default value of this property is (0.5, 0.5), which represents the center of the layer’s bounds rectangle.

All geometric manipulations to the view occur about the specified point.

For example, applying a rotation transform to a layer with the default anchor point causes the layer to rotate around its center. Changing the anchor point to a different location would cause the layer to rotate around that new point.

anchorPoint的值在 (0,0)(1,1)之间。默认是 (0.5, 0.5),代表锚点在中心位置。 (0,0)(1,1)分别代表左上角和右上角。

  1. 关于CALayer的属性positionanchorPoint
  • position类似UIViewcenter
  • position决定了layer在父视图上的位置
  • anchorPoint决定了position在自身的位置。All geometric manipulations to the view occur about the specified point.
  1. CADisplayLink 与 NSTimer
  • CADisplayLink精确度高
  • NSTimer占用系统资源较多

代码和图片位置: 89-Animation/clock

iOS动画(一):时钟动画(Swift)-JEESNS
欢迎您访问我的的微信公众号:欣欣向戎(微信号: andy_ron1587 )!
文章评论

2 关注 / 24 粉丝

我无话可说