1

我有一些我运行连续动画的图像。如何平滑地更新这些正在运行的动画,以便它们之间没有可见的过渡,除非是动画的一部分。

例如旋转和缩放图像,然后更新动画以原样旋转,但稍微放大。我目前得到了明显的变化。

我可以想象应该在动画块内完成缩放,并且他们只是像以前一样运行旋转动画,问题是旋转会在放大时停止。

我需要它是无缝的。例如,这个代码块不会导致平滑缩放,即使它使用UIViewAnimationOptionBeginFromCurrentState

[UIView animateWithDuration:0.5
                      delay:0
                    options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseOut //| UIViewAnimationOptionRepeat
                 animations:(void (^)(void)) ^{
                     imageViewToScale.transform = CGAffineTransformMakeScale(1.2, 1.2);
                 }
                 completion:^(BOOL finished){
                     //imageViewToScale.transform=CGAffineTransformIdentity;
                 }];
4

1 回答 1

2

老实说,如果您的视图上有连续的动画,这将在运行时改变那里的状态 UIView 动画不是他最好的方法,并且可能会导致抖动,而完成处理程序被一遍又一遍地调用等等

但是,如果您想在块中制作 2 个动画,您可以在同一块中设置比例和旋转,它们将同时发生。或者您可以调用一个函数来启动该块并在完成时再次调用它以查看该视图是否有任何新动画。当没有时,完成块就会停止,有点递归地使用它们,尽管如果你连续在很多视图上做很多动画,这不是我不推荐的方法。

在 OpenGLES 中,您使用 NSTimer 运行连续动画,以处理应用程序中所有动画的更新。如果你走这条路,它会付出更多的努力,你需要自己实现缓动/二次曲线函数以实现平滑动画。但是,如果您扩展类,您可以为每个图像设置状态,然后当计时器触发时,您可以根据您给它的状态更新它的转换。因此,当它旋转了一定的度数/弧度时,您可以将其设置为缩放。现在为了保持动画流畅,您需要使用 NSTimerIntervals 来确保将移动的距离乘以经过的时间,以获得流畅的动画。就个人而言,这是我用于可能在屏幕上不断移动的东西的路线,但如果你只需要移动两次然后完成,则可能会过度杀戮。

编辑:按照您的要求执行第二步的代码!

因此,您需要声明一个将轮询您的动画步骤的 NSTimer 和一个 NSTimeInterval,以便您仅根据已过去的时间量来更新每个步骤的动画。

NSTimer *animationTimer;
NSTimeInterval animationInterval;
NSTimeInterval lastUpdateTime;
float currentRotation;
float current scale;

第三,你需要设置一个 NSTimer 来更新你的视图:

- (void)startAnimation
{
    animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView:) userInfo:nil repeats:YES];
}

- (void)stopAnimation
{    
    [animationTimer invalidate];
    animationTimer = nil;
}

然后你需要在你的视图开始时或者当你想开始动画时开始做这样的事情

- (void)setAnimationInterval:(NSTimeInterval)interval
{
    animationInterval = interval;

    if(animationTimer)
    { 
        [self stopAnimation];
        [self startAnimation];
    } 
} 

然后在您的 drawView: 方法中,您需要根据每次计时器触发之间经过的时间来更新您的变换,以便动画随着时间的推移平滑且恒定。此时基本上是线性变换。

- (void)drawView:(id)sender
{
    if(lastUpdateTime == -1)
    {
        lastUpdateTime = [NSDate timeIntervalSinceReferenceDate];
    }

    NSTimeInterval timeSinceLastUpdate = [NSDate timeIntervalSinceReferenceDate] - lastUpdateTime;

    currentRotation = someArbitrarySCALEValue * timeSinceLastUpdate;
    currentScale = someArbitraryROTATIONValue * timeSinceLastUpdate;

    CGAffineTransform scaleTrans =  CGAffineTransformMakeScale(currentScale,currentScale);
    CGAffineTransform rotateTrans =  CGAffineTransformMakeRotation(currentRotation * M_PI / 180);

    imageViewToScale.transform = CGAffineTransformConcat(scaleTrans, rotateTrans);


    lastUpdateTime = [NSDate timeIntervalSinceReferenceDate];
}

请注意,这不会为您的动画添加缓动,也不会在物理上停止您需要使用它。此外,您可能需要确保当旋转超过 360 度时将其重置为 0,并分别在度数和弧度之间进行转换。

考虑使用物理学来处理反弹和摩擦以使事情变慢。

查看二次图以使事情随着时间的推移平滑移动,本质上是二次插值。

于 2013-05-28T09:09:50.213 回答