0
votes

I am trying to rotate a CALayer by a little less than 360 degrees but instead the transform rotates it in opposite direction (that is smaller of the two angles). How can I achieve this rotation given I am also applying a translation transform on the layer? Also, I want to be able to control the direction of rotation. It seems CAAnimation wouldn't heed and take the shorter angle of the transform for rotation. It seems these two problems are perhaps related. Here's how part of my swift code looks:

func addAnimation() {
    var animation : CABasicAnimation = CABasicAnimation(keyPath: "transform")

    animation.delegate = self

    let translateDistY = CGRectGetMidY(self.view.bounds) - CGRectGetMidY(self.displayLayer.bounds)
    let rotationAngle = (CGFloat(M_PI*2.0) - 0.1)

    var transform : CATransform3D = CATransform3DMakeTranslation(0, translateDistY, 0)
    transform = CATransform3DRotate(transform, rotationAngle, 0, 0, 1)

    animation.fromValue = NSValue(CATransform3D: CATransform3DIdentity)
    animation.toValue = NSValue(CATransform3D: transform)

    animation.duration = 1.3
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

    let animStruct = animationStruct(animLayer: self.displayLayer, animation: animation, layerTransform: transform)

    self.animationSequence.append(animStruct)
}

func doAnimation() {
    if  animationSequence.count > 0 {
        let animStruct = animationSequence.removeAtIndex(0)
        animStruct.animLayer.transform = animStruct.layerTransform
        animStruct.animLayer.addAnimation(animStruct.animation, forKey: nil)
    }
}

override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
    self.doAnimation()
}
2

2 Answers

0
votes

There does not seems any way to rotate however you like using normal transform animation. One way to do this is by using custom layer properties. See this great post from Nick Lockwood.

http://www.objc.io/issue-12/animating-custom-layer-properties.html

0
votes

I have some solution to this problem but I am not sure if this is correct or if there is a better solution. Nonetheless, here follows the swift code:

func addAnimation() {
    let translateByValueY = CGRectGetMidY(self.view.bounds) - CGRectGetMidY(self.diaplayLayer.bounds)

    var animRotateZ : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
    animRotateZ.duration = 1.5
    animRotateZ.toValue = NSNumber(double: -0.2)
    animRotateZ.byValue = NSNumber(double: 2.0 * M_PI)
    animRotateZ.delegate = self
    animRotateZ.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
    animRotateZ.setValue(self.diaplayLayer, forKey: "animationLayer")
    self.animationSequence.append(animRotateZ)

    var animTranslateY : CABasicAnimation = CABasicAnimation(keyPath: "transform.translation.y")

    animTranslateY.duration = 1.5
    animTranslateY.toValue = NSNumber(double: Double(CGRectGetMidY(self.view.bounds)))
    animTranslateY.byValue = NSNumber(double: Double(translateByValueY))
    animTranslateY.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
    animTranslateY.setValue(self.diaplayLayer, forKey: "animationLayer")
    self.animationSequence.append(animTranslateY)

}

func doAnimation() {
    if animationSequence.count > 0 {
        let animRotateZ = animationSequence.removeAtIndex(0)
        let animationRotateZLayer = animRotateZ.valueForKey("animationLayer") as CALayer

        animationRotateZLayer.setValue(animRotateZ.toValue, forKeyPath: "transform.rotation.z")
        animationRotateZLayer.addAnimation(animRotateZ, forKey: animRotateZ.keyPath)

        let animTranslateY = animationSequence.removeAtIndex(0)
        let animationTranslateYLayer = animTranslateY.valueForKey("animationLayer") as CALayer

        animationTranslateYLayer.setValue(animTranslateY.toValue, forKeyPath: "transform.translation.y")
        animationTranslateYLayer.addAnimation(animTranslateY, forKey: animTranslateY.keyPath)
    }
}

override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
    self.doAnimation()
}

I drew a lot of information from following posts on stackoverflow, may thanks to them:

Using CABasicAnimation to rotate a UIImageView more than once

How to chain different CAAnimation in an iOS application