Перемещение изображения по серии CGPoints - PullRequest
5 голосов
/ 12 февраля 2012

У меня есть путь, сохраненный в массиве 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 ]

4 голосов
/ 12 февраля 2012

В вашем коде предполагается, что анимации 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 Animation

- (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];
}
2 голосов
/ 12 февраля 2012

Хорошо, вам нужно установить массив точек как свойство класса, что-то вроде 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 s анимации управляют вещами в других потоках, поэтому, вероятно, поэтому оператор for не работает.

...