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

查看:186
本文介绍了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.


  • 比例最好是 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天全站免登陆