How to make a CATransform3dMakeRotation rotate the other way? And chain together

流过昼夜 提交于 2019-12-04 10:43:34
Brad Larson

I believe that what you want in this case is to use a helper keypath like is described in this answer:

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI];
rotationAnimation.duration = duration;
[myCard.layer addAnimation:rotationAnimation forKey:@"rotationAnimation1"];

which should rotate about the X axis for the first stage of your animation. For the second, I believe if you use the following

CABasicAnimation *rotationAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
rotationAnimation2.toValue = [NSNumber numberWithFloat: M_PI];
rotationAnimation2.duration = duration2;
rotationAnimation2.cumulative = YES;
[myCard.layer addAnimation:rotationAnimation2 forKey:@"rotationAnimation2"];

it should make the animations cumulative and may produce the desired effect. I haven't tried this myself, so some tinkering may be required to get the exact result you need.

When you are working with a transform directly, Core Animation will interpolate the transform from the current value to the specified transform. It will find the shortest path to get to that transform, which will restrict the animation direction. If you try to animate the same transform property twice, the second value will simply override the first, not combine the two transforms together.

However, when using a helper keypath like this, Core Animation will interpolate between your starting angle and ending angle, so you can reverse direction by changing the sign of the ending angle. It optimizes the change in angle value, not the change in the underlying transform. You also should be able to combine animations on the keypath, because the transform is generated for you under the hood for each combination of keypath manipulations.

I'm guessing the flipping on an axis is caused by gimbal lock happening inside Apple's library. The easy fix that works 99.999% of the time is to just not use exact 0, 90, 180, 270, and 360 degree rotations. I've seen stuff like this happen in my code, but I just use something like (M_PI*0.99) instead of M_PI. This is always a problem if you are using the video card's matrix multipliers with euler angles.

To apply multiple transforms at the same time, you can nest them. This works exactly like multiplying matrices in OpenGL.

// translate and scale at the same time
float scale = 1.6;
CATransform3D scaleMatrix = CATransform3DMakeScale(scale, scale, 1);
CATransform3D finalMatrix = CATransform3DTranslate(scaleMatrix, frame.size.width/scale, frame.size.height/scale, 0);
CABasicAnimation* animBottomTrans = [CABasicAnimation animationWithKeyPath:@"transform"];
[animBottomTrans setFromValue:[NSValue valueWithCATransform3D:finalMatrix]];
[animBottomTrans setToValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
[animBottomTrans setDuration:duration];
[myLayer addAnimation:animBottomTrans forKey:@"transform"];

Remember that since these are nested you have to deal with the previous transform in any transforms that come after it. In this code I have to change the amount I translated because I have already scaled. If you rotate 90degrees on the z axis and then rotate 90 degrees on the y axis, you have effectively just rotated on the z and x axises (the z rotation swaps your x and y axises).

The resulting transform is the same: (CGAffineTransform){-1,0,0,-1,0,0}. CoreAnimation picks the shortest rotation that will do the trick, and defaults to rotating clockwise (I think).

The easiest way to rotate the other way is to rotate by almost -M_PI (I'm not sure exactly how close you can get before it decides to rotate the "wrong" way).

The more complicated way is to break it up into two rotations: one from 0 to -M_PI/2 and one from -M_PI/2 to -M-PI. I think you can set an animation delay to make this happen...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!