CABasicAnimation忽略持续时间

时间:2015-09-20 14:44:17

标签: swift cocoa core-animation

无论是否使用CATransation,我似乎都无法控制简单Core Animation的持续时间。

交易完成代码在我的期限设置之后触发,就像我期望的那样,但无论设置的持续时间如何,旋转动画总是需要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)
    }


}

另一方面,我使用了一些有用的扩展...在NSBezierPath中使用了toCGPath,在CGFloat中使用了DegreeToRadians。

2 个答案:

答案 0 :(得分:1)

您看到这种奇怪行为的原因是使用显式CATransaction begin - commit。这将反过来在运行循环已拥有的CATransaction中添加嵌套的CATransaction。所以会发生什么,你的内部事务被提交,但在关联的动画完成之前,你有一个转换的直接新值。这将导致您的图层快速旋转和消失的故障。

而不是这样,直接的做法是 1.创建动画 2.为动画设置委托 3.在委托回调中设置您希望图层保留的目标值。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/new_formulas"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/add_hint"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="@string/add_hint"
            android:textSize="30dp" />

        <Button
            android:id="@+id/add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/add"
            android:textSize="30dp" />
    </LinearLayout>

</LinearLayout>

P.S:我还没有运行这段代码,并且还要注意在动画完成后确定要为图层转换设置的值。

答案 1 :(得分:0)

我认为问题是因为你的startAngle和endAngle。尝试像这样改变它。这对我有用

private let startAngle: CGFloat = CGFloat(-M_PI_2) 
private let endAngle: CGFloat = CGFloat(-M_PI_2) + CGFloat(M_PI * 2)