沿着一系列CGPoints移动图像

时间:2012-02-12 02:35:26

标签: iphone ios ipad uikit core-animation

我有路径存储在CGPoints数组中,我想移动图像。这是我到目前为止的一般代码:

-(void)movePic:(id)sender{
    for(int i = 0; i < self.array.count; i++){
        CGPoint location = [[self.array objectAtIndex:i] CGPointValue];
        [UIView animateWithDuration:0.1 animations:^{
            self.imageView.center = location;
        } completion:^(BOOL finished){
        }];
    }
}

问题是for循环运行得非常快,所以你只能看到最后几点的动画。我不确定如何更好地设计这个。理想情况下,我可以做些什么来确保一个动画在另一个动画开始之前完成?我不应该使用for循环吗?感谢

2 个答案:

答案 0 :(得分:4)

您的代码假定UIView动画在主线程中同步运行,而不是。

您似乎有两个选择

  • 明确CAKeyframeAnimation,可沿任意数量的采样点设置CALayer动画(在它们之间进行插值)
  • 隐式递归UIView动画,用于沿着一系列采样点设置UIView动画(在它们之间进行插值)

前者会更有效率 - 我仍然认为我可以向你展示两种选择。

CAKeyframeAnimation

- (void)movePic:(id)sender
{
    //create a mutable core-graphics path
    CGMutablePathRef path = CGPathCreateMutable();
    for(int i = 0; i < self.array.count; i++)
    {
        CGPoint location = [[self.array objectAtIndex:index] CGPointValue];
        CGPathAddLineToPoint(path, nil, location.x, location.y);
    }
    //create a new keyframe animation
    CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //add our path to it
    pathAnimation.path = path;
    //be nice to the system
    CGPathRelease(path);
    //setup some more animation parameters
    pathAnimation.duration = 0.1 * self.array.count;
    //add the animation to our imageView's layer (which will start the animation)
    [self.imageView.layer addAnimation:pathAnimation forKey:@"pathAnimation"];
}

UIView动画

- (void)movePicToPointAtIndex:(unsigned int)index
{
    //safeguard check...
    if ([self.array count] <= index)
        return;
    //get the next location
    CGPoint location = [[self.array objectAtIndex:index] CGPointValue];
    //animate the imageView center towards that location
    [UIView animateWithDuration:0.1 
                          delay:0.0 
                        options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
                     animations:^{
        self.imageView.center = location;
    } completion:^(BOOL finished){
        //we are done with that animation, now go to the next one...
        [self movePicToPointAtIndex:index+1];
    }];
}

- (void)movePic:(id)sender
{
    [self movePicToPointAtIndex:0];
}

答案 1 :(得分:2)

好的,你要做的就是将点数组设置为类的属性,如animationPath。好的,所以现在你必须注意UIView动画委托方法的委托方法(它实际上不是一个不同的类,它只是类'方法的委托)。

设置一个方法,每次动画停止时调用setAnimationDidStopSelector:selector,所以在这里你会有这样的事情:

//Inside the callback for setAnimationDidStopSelector
if ([animationPath count] != 0){
    //Go to next point
    CGPoint location = [[self.array objectAtIndex:0] CGPointValue];
    [UIView animateWithDuration:0.1 animations:^{
        self.imageView.center = location;
    } completion:^(BOOL finished){
    }];
}
else{
    NSLog(@"Nowhere else to go, animation finished :D");
}

因此,请务必使用第一点启动动画。

据我记得UIView的动画管理其他线程中的内容,这可能就是for语句无效的原因。