iOS:同步缩放和 3D 旋转动画 [英] iOS: Simultaneous scale and 3D rotation animation

查看:51
本文介绍了iOS:同步缩放和 3D 旋转动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个视频来演示我正在尝试完成的动画:在这里.

I made a video demonstrating the animation i'm trying to accomplish: Here it is.

请注意,视频展示了从侧面看到的动作.相机图标代表用户的 POV.它基本上是对通过缩放变换完成的 Z 轴之间的平移的模拟,同时沿 X 轴发生独立的两步 3D 旋转.

Notice the video illustrates the action as it would be seen from the side. The camera icon represents the user's POV. It's basically a simulation of a translation among the Z-axis accomplished though a scale transform, with a simultaneous independent two-step 3D rotation happening along the X axis.

看起来和听起来都很简单,对吧?错误的.这是理想的代码,但它不起作用:

Looks and sounds simple enough, right? Wrong. Here's the ideal code, which doesn't work:

[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 旋转将被完全忽略.我尝试了许多其他方法,但都失败了.

Turns out, if you do this, the 3D rotation gets ignored completely. I've tried a number of other approaches, and they all have failed.

  • Scale 最好是一个 CGAffineTransform
  • 缓动应该如图所示,尤其是在旋转时

当然,如果出现需要更改其中一些的解决方案,我可以适应.

Of course, if a solution comes up that requires some of these to change, I could adapt.

在此先感谢您的帮助.如果您需要澄清,请务必询问.

Thanks in advance for any help. If you need clarification, please do ask.

推荐答案

如果不取消第一个动画,您就无法为同一属性设置动画.您应该使用 Core Animation 并执行两个动画或一个关键帧动画.

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.

通过创建一个用于缩放的动画(如果需要,您可以将其作为 z 平移)和一个用于旋转的动画,为它们提供非常具体的关键路径,它们不会相互抵消.

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)

视角

在这两种情况下,我都通过在动画视图的超层上设置 sublayerTransform 来实现透视(假设那里只有一个带有变换的子视图)

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;

这篇关于iOS:同步缩放和 3D 旋转动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆