iOS动画:CADisplayLink vs CAShapeLayer

问题描述:

我正在写一个计时器,类似于水平版本的时钟应用程序中可用的计时器,只是它开始已满并且向下运行为空。因为我使用drawRect方法进行动画制作,所以我实现了计时器,它适用于较大的时间,但它无法快速进行动画快速动画处理(我的动画时间最快为400ms)。为了说明这一点,这是我的计时器代码:iOS动画:CADisplayLink vs CAShapeLayer

class SSTimerView: UIView { 
    var timer: NSTimer? 
    var startAngle: CGFloat = (CGFloat) (M_PI * 1.5) 
    var endAngle: CGFloat = (CGFloat) (M_PI * 1.5) + (CGFloat) (M_PI * 2) 
    var percent: CGFloat? = 100 

    required init(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
    } 

    override func drawRect(rect: CGRect) { 
     var bezierPath = UIBezierPath() 
     //Create our arc with the correct angles 
     bezierPath.addArcWithCenter(CGPointMake(rect.size.width/2, rect.size.height/2), 
      radius: 130, 
      startAngle: startAngle, 
      endAngle: (endAngle - startAngle) * (percent!/100.0) + startAngle, 
      clockwise: true 
     ) 
     //Set the display for the path and stroke it. 
     bezierPath.lineWidth = 20 
     Slide.sharedInstance.currentInstruction!.colorFamily.lighterColor.setStroke() 
     bezierPath.stroke() 
    } 
} 

我一直在阅读CADisplayLink了,我认为这可能是一个可行的选择,但我也听说CADisplayLink并不适用于所有情况。这是他们中的一员吗?如果CADisplayLink在这里不合适,我应该使用哪个CA类?

如您所知,手动动画CADisplayLink始终优于NSTimer。 (有关讨论的原因,请参阅WWDC 2014视频Building Interruptible and Responsive Interactions,从视频开始约14分钟。)因此,如果您坚持现有模式,请务必转至CADisplayLink

但是,如果你想动画这个路径的绘制,CABasicAnimation要容易得多:

var shapeLayer: CAShapeLayer! 

func addShapeLayer() { 
    shapeLayer  = CAShapeLayer() 
    let startAngle = CGFloat(M_PI * 1.5) 
    let endAngle = startAngle + CGFloat(M_PI * 2) 

    let bezierPath = UIBezierPath() 

    bezierPath.addArcWithCenter(CGPointMake(view.bounds.size.width/2, view.bounds.size.height/2), 
     radius: 130.0, 
     startAngle: startAngle, 
     endAngle: endAngle, 
     clockwise: true 
    ) 

    shapeLayer.path  = bezierPath.CGPath 
    shapeLayer.strokeColor = UIColor.blueColor().CGColor 
    shapeLayer.fillColor = UIColor.clearColor().CGColor 
    shapeLayer.lineWidth = 20.0 

    view.layer.addSublayer(shapeLayer) 
} 

func animateShapeLayer() { 
    let animation  = CABasicAnimation(keyPath: "strokeEnd") 
    animation.duration = 0.4 
    animation.fromValue = 0.0 
    animation.toValue = 1.0 
    shapeLayer.addAnimation(animation, forKey: "strokeEndAnimation") 
} 

CADisplayLink的做法是巨大的,如果你需要更多的个性化的行为,但如果你只是想动画的绘制一段时间内的路径,CABasicAnimation是最简单的(并且可能提供最佳性能)。

+0

我很喜欢你的建议。我最初使用它,但我对隐式动画非常不满。所以,我修改了你的解决方案,包括CADisplayLink,其中我正在计算和动画计算每个帧的计时器应该具有的填充百分比。这对我来说工作得非常好,因为我可以将控制逻辑添加到定时器(“如果定时器用完并满足这些条件,则......”),暂停并重新启动定时器,并且它更有效地运行CONSIDERABLY(