无论是否使用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。
答案 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)