我制作了一段视频,演示了我想要完成的动画:Here it is.
请注意,视频说明了从侧面看到的操作。相机图标代表用户的POV。它基本上是通过比例变换完成Z轴之间平移的模拟,同时沿X轴发生同步的两步3D旋转。
看起来和听起来很简单,对吗?错误。这是理想的代码,不起作用:
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
view.transform = CGAffineTransformMakeScale(1.0, 1.0);
} completion:^(BOOL finished) {}];
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CATransform3D rotation = CATransform3DIdentity;
rotation.m34 = 1.0 / - 1800;
rotation = CATransform3DRotate(rotation, - 20 * M_PI / 180.0f, 1, 0, 0);
view.layer.transform = rotation;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
view.layer.transform = CATransform3DIdentity;
} completion:^(BOOL finished) {}];
}];
事实证明,如果这样做,3D旋转将被完全忽略。我尝试过其他一些方法,但都失败了。
CGAffineTransform
当然,如果出现需要改变其中一些的解决方案,我可以适应。
提前感谢您的帮助。如果您需要澄清,请询问。
答案 0 :(得分:27)
如果没有取消第一个动画,则无法为同一属性设置动画。您应该使用Core Animation并执行两个动画或一个关键帧动画。
通过创建一个用于缩放的动画(如果需要,您可以将其作为z-translation执行)和一个用于旋转的动画,为它们提供非常特定的键路径,它们将不会相互抵消。
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)
由于您有三个非常好的关键帧,因此在三个关键帧之间设置动画的代码将易于阅读和理解。如果你想改变缩放的时间与旋转的时间分开,你可能会失去一些控制。
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)
在这两种情况下,我通过在动画视图的超层上设置sublayerTransform来做透视(假设只有一个带有变换的子视图)
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = 1.0 / - 1800.0;
view.superview.layer.sublayerTransform = perspective;
答案 1 :(得分:2)
我找到了一种方法,但它更像是一种黑客攻击。执行以下操作 -
1)创建一个透明背景的视图 - (此视图将翻译) 2)创建1)的子视图 - (此视图将旋转)。
现在使用创建两个变换,视图1的缩放变换和视图2的旋转变换)并同时应用它们。