2016-05-12 43 views
1

我已成立了一个CADisplayLink调用以下drawCircle()功能在10秒内以画圆的路径动画:CAShapeLayer行程未完成

func drawCircle() { 
    currentDuration = currentDuration + displayLink.duration 
    circleLayer.strokeEnd = min(CGFloat(currentDuration/maxDuration), 1) 

    if (currentDuration >= maxDuration) { 
     stopCircleAnimation() 
    } 
} 

func stopCircleAnimation() { 
    let pausedTime = circleLayer.convertTime(CACurrentMediaTime(), fromLayer: nil) 
    circleLayer.speed = 0 
    circleLayer.timeOffset = pausedTime 
} 

其中currentDuration是经过时间,maxDuration等于到10.这工作正常,除了currentDuration >= maxDuration。即使strokeEnd设置为1,它也不会完全完成圆。为什么是这样??

编辑

我认为它可能有一些做的circleLayerspeed财产。如果我把它设置得更高一些,例如10,那么这个圆圈是完全关闭的。

回答

0

这是由于设置你的CAShapeLayerstrokeEnd生成一个隐动画新价值的事实。然后在动画完成之前将图层的速度设置为零,因此“暂停”动画,以使其显示为“不完整”。

虽然您可以通过禁用隐含动画来解决问题,但您应该考虑在此处使用CADisplayLink是否真的合适。核心动画设计为首先生成和运行动画,通过生成自己的中间步骤,为什么不通过显式或隐式动画显示层strokeEnd来实现相同的结果?

这里是你如何能做到这一点有一个隐含的动画的例子:

CATransaction.begin() 
CATransaction.setAnimationDuration(10) 

// if you really want a linear timing function – generally makes the animation look ugly 
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)) 

circleLayer.strokeEnd = 1 
CATransaction.commit() 

或者,如果你想把它当作一个明确的动画:

let anim = CABasicAnimation(keyPath: "strokeEnd") 
anim.fromValue = 0 
anim.toValue = 1 
anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
anim.duration = 10 
circleLayer.addAnimation(anim, forKey: "strokeEndAnim") 

// update model layer value 
CATransaction.begin() 
CATransaction.setDisableActions(true) 
circleLayer.strokeEnd = 1 
CATransaction.commit() 
+0

其实我需要使用CADisplayLink因为我如果将它与视频时间一起使用,则需要尽可能精确。不过,关于禁用CATransaction操作是正确的(正如我在发布答案之前发现的那样)。我会接受你的回答,因为你已经详细了解了。 – Tometoyou

0

找到了答案 - 设置strokeEnd属性时禁用动画:

CATransaction.begin() 
CATransaction.setDisableActions(true) 
circleLayer.strokeEnd = min(CGFloat(currentDuration/maxDuration), 1) 
CATransaction.commit()