2015-09-20 4 views
0

Я не могу контролировать длительность простой анимации ядра, использую ли я CATransation или нет.CABasicAnimation игнорирует длительность

Код завершения транзакции срабатывает после моей настройки продолжительности, как и следовало ожидать, но анимация вращения всегда занимает около 0,5 секунды независимо от того, на какой длительности она установлена.

Но если я прокомментирую последнюю строку, которая устанавливает преобразование, анимация движется с правильной скоростью, а затем снова возвращается к первоначальному вращению.

Что мне не хватает?

class MyControl: NSControl { 
    var shapeLayer = CAShapeLayer() 

    required override init(frame frameRect: NSRect) { 
     super.init(frame: frameRect) 
     self.wantsLayer = true 
     self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay 

     // create a triangle shape 
     let path = NSBezierPath() 
     path.moveToPoint(CGPointMake(45.0, 25.0)) 
     path.lineToPoint(CGPointMake(5.0, 5.0)) 
     path.lineToPoint(CGPointMake(5.0, 45.0)) 
     path.lineToPoint(CGPointMake(45.0, 25.0)) 
     path.closePath() 
     shapeLayer.frame = self.bounds 
     shapeLayer.path = path.toCGPath() 
     shapeLayer.fillColor = NSColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0).CGColor 
     self.layer!.addSublayer(shapeLayer) 
    } 

    override func mouseUp(theEvent: NSEvent){ 
     let duration = 2.0 
     let endAngle = -90.0 
     let startAngle = shapeLayer.valueForKey("transform.rotation") 

     CATransaction.begin() 
     CATransaction.setAnimationDuration(duration) 
     CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)) 
     CATransaction.setCompletionBlock({ 
      Swift.print("this fires after 2 seconds") 
     }) 

     let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation") 
     rotateAnimation.removedOnCompletion = true 
     rotateAnimation.autoreverses = false 
     rotateAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
     rotateAnimation.duration = duration 
     rotateAnimation.fromValue = startAngle 
     rotateAnimation.toValue = endAngle.degreesToRadians 
     shapeLayer.addAnimation(rotateAnimation, forKey: rotateAnimation.keyPath) 
     CATransaction.commit() 

     // mystery line... 
     shapeLayer.transform = CATransform3DMakeRotation(endAngle.degreesToRadians, 0.0, 0.0, 1.0) 
    } 


} 

На стороне записки, я использовал несколько полезных расширений ... toCGPath в NSBezierPath и degreesToRadians для CGFloat.

+0

Переместить тайну в ваш блок завершения – Shripada

+0

Это не работает. – pizzafilms

ответ

1

Причина, по которой вы видите это странное поведение, - использование явного CATransaction begin-commit. Это, в свою очередь, добавит вложенное CATransaction в пределах, уже принадлежащих циклу запуска. Итак, что происходит, ваша внутренняя транзакция завершается, но до того, как соответствующая анимация закончится, у вас есть немедленное новое значение для преобразования. Это вызовет этот сбой, когда ваш слой будет просто быстро вращаться и исчезать.

Вместо этого, прямой способ сделать это 1. Создайте анимацию 2. Установите делегат для анимации 3. В делегат обратного вызова установить целевое значение, которое вы хотели бы слой, чтобы остаться в.

override func mouseUp(theEvent: NSEvent){ 
    let duration = 2.0 
    let endAngle = -90.0 
    let startAngle = shapeLayer.valueForKey("transform.rotation") 

    //Set up animation 
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation") 
    rotateAnimation.removedOnCompletion = true 
    rotateAnimation.autoreverses = false 
    rotateAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
    rotateAnimation.duration = duration 
    rotateAnimation.fromValue = startAngle 
    rotateAnimation.toValue = endAngle * 3.142/180 

    //Setup delegate 
    rotateAnimation.delegate = self 

    shapeLayer.addAnimation(rotateAnimation, forKey: @"rotationAnimation") 

    } 


    public override func animationDidStop(anim: CAAnimation, finished flag: Bool){ 
    shapeLayer.transform = CATransform3DMakeRotation(CGFloat(-90.0 * 3.142/180), 0.0, 0.0, 1.0) 
    } 

PS: Я не запускать этот код, а также отметить уверены, что значение, которое вы хотите установить для преобразования вашего слоя после того, как анимация завершается.

0

Я думаю, проблема в том, что ваш startAngle и endAngle. Попытайтесь изменить его так. Это работает для меня

private let startAngle: CGFloat = CGFloat(-M_PI_2) 
private let endAngle: CGFloat = CGFloat(-M_PI_2) + CGFloat(M_PI * 2) 
Смежные вопросы