iOS: Simultaneous scale and 3D rotation animation

做~自己de王妃 提交于 2019-11-30 04:14:19

You can't animate the same property without the first animation being canceled. You should drop down to using Core Animation and either doing two animations or one keyframe animation.

Two transformation animations

By creating one animation for scaling (which you could do as z-translation if you want) and one for rotating giving them very specific key paths they will not cancel each other.

CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scale.fromValue = @0.75; // Your from value (not obvious from the question)
scale.toValue = @1.0;
scale.duration = 0.4;
scale.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

CAKeyframeAnimation *rotate = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.x"];
rotate.values = @[@0.0, @(- 20 * M_PI / 180.0f), @0.0];
rotate.duration = 0.4;
rotate.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

[view.layer addAnimation:scale forKey:@"move forward by scaling"];
[view.layer addAnimation:rotate forKey:@"rotate back and forth"];
view.transform = CGAffineTransformIdentity; // Set end value (animation won't apply the value to the model)

A single keyframe animation

Since you have three very good keyframes the code to animate between the three keyframes would be easy to read and understand. You would possibly lose some of the control if you wanted to change the timing of the scaling separate from that of the rotating.

CATransform3D firstFrame  = CATransform3DMakeScale(0.75, 0.75, 1.0);
CATransform3D secondFrame = CATransform3DMakeScale(0.875, 0.875, 1.0); // halfway to 1.0 from 0.75
secondFrame = CATransform3DRotate(secondFrame, -20.0*M_PI/180.0, 1.0, 0.0, 0.0);
CATransform3D lastFrame   = CATransform3DIdentity;

CAKeyframeAnimation *scaleAndRotate = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
scaleAndRotate.values = @[[NSValue valueWithCATransform3D:firstFrame],
                          [NSValue valueWithCATransform3D:secondFrame],
                          [NSValue valueWithCATransform3D:lastFrame] ];
scaleAndRotate.duration = 1.0;
scaleAndRotate.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

[view.layer addAnimation:scaleAndRotate forKey:@"entire animation"];
view.transform = CGAffineTransformIdentity; // Set end value (animation won't apply the value to the model)

Perspective

In both cases I did the perspective by setting the sublayerTransform on the superlayer of the animating view (assuming there is only one subview with a transform there)

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = 1.0 / - 1800.0;    
view.superview.layer.sublayerTransform = perspective;

I found a way but its more like a hack. Do the following -

1)create a view with transparent background - (this view will translate) 2)create a subview of 1) - (this view will rotate).

Now use create two transforms, a scaling transform for view 1) and a rottaion transform for view 2) and apply them simultaneously.

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