Fork me on GitHub

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

一、直接做动画

  • 新建项目clock
  • 加载表盘图片。

    viewDidLoad中添加:

    1
    2
    3
    4
    5
    6
    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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    // 秒针
    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中添加:

    1
    2
    3
    4
    5
    6
    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中添加:

    1
    2
    let link = CADisplayLink(target: self, selector: #selector(ViewController.clockRunning))
    link.add(to: RunLoop.main, forMode: .defaultRunLoopMode)
  • 添加方法clockRunning:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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(锚点)
    如果注释掉分针和时针视图,并且关掉动画效果和锚点设置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //        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)

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

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.
  2. CADisplayLink 与 NSTimer

    • CADisplayLink精确度高
    • NSTimer占用系统资源较多

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

参考:

坚持原创技术分享,您的支持将鼓励我继续创作!
  • 本文标题: iOS动画(一):时钟动画(Swift)
  • 本文作者: AndyRon
  • 发布时间: 2017年09月05日 - 13:02
  • 最后更新: 2018年09月20日 - 02:49
  • 本文链接: http://andyron.com/2017/ios-animation-1-clock.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!