How do i rotate a CALayer around a diagonal line?

前端 未结 3 1749
旧巷少年郎
旧巷少年郎 2021-01-31 21:42

I\'m trying to implement a flip animation to be used in board game like iPhone-application. The animation is supposed to look like a game piece that rotates and changes to the c

3条回答
  •  广开言路
    2021-01-31 22:11

    I got it solved. You probably already have a solution as well, but here is what I have found. It is quite simple really...

    You can use a CABasicAnimation to do the diagonal rotation, but it needs to be the concatenation of two matrices, namely the existing matrix of the layer, plus a CATransform3DRotate. The "trick" is, in the 3DRotate you need to specify the coordinates to rotate around.

    The code looks something like this:

    
    CATransform3DConcat(theLayer.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0));
    

    This will make a rotation that appears as though the upper-left corner of the square is rotating around the axis Y=X, and travelling to the lower-right corner.

    The code to animate looks like this:

    
    CABasicAnimation *ani1 = [CABasicAnimation animationWithKeyPath:@"transform"];
    
    // set self as the delegate so you can implement (void)animationDidStop:finished: to handle anything you might want to do upon completion
    [ani1 setDelegate:self];
    
    // set the duration of the animation - a float
    [ani1 setDuration:dur];
    
    // set the animation's "toValue" which MUST be wrapped in an NSValue instance (except special cases such as colors)
    ani1.toValue = [NSValue valueWithCATransform3D:CATransform3DConcat(theLayer.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0))];
    
    // give the animation a name so you can check it in the animationDidStop:finished: method
    [ani1 setValue:@"shrink" forKey:@"name"];
    
    // finally, apply the animation
    [theLayer addAnimation:ani1 forKey@"arbitraryKey"];
    

    That's it! That code will rotate the square (theLayer) to invisibility as it travels 90-degrees and presents itself orthogonally to the screen. You can then change the color, and do the exact same animation to bring it back around. The same animation works because we are concatenating the matrices, so each time you want to rotate, just do this twice, or change M_PI/2 to M_PI.

    Lastly, it should be noted, and this drove me nuts, that upon completion, the layer will snap back to its original state unless you explicitly set it to the end-animation state. This means, just before the line [theLayer addAnimation:ani1 forKey@"arbitraryKey"]; you will want to add

    
    theLayer.transform = CATransform3DConcat(v.theSquare.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0));
    

    to set its value for after the animation completes. This will prevent the snapping back to original state.

    Hope this helps. If not you then perhaps someone else who was banging their head against the wall like we were! :)

    Cheers,

    Chris

提交回复
热议问题