Как прекратить анимацию в iPhone-OS? - PullRequest
3 голосов
/ 17 мая 2009

У меня есть класс "Cube" и есть метод -rotate. Метод устанавливает точку привязки внизу слева, а затем поворачивает куб на 90 градусов. После этого вызывается другой метод, который заставляет куб поворачиваться назад на -90 градусов. Это сделано с указанием селектора остановки. Кстати: это не имеет никакого специального назначения. Просто учусь!

-rotate вызывается при сенсорном событии. Но теперь, когда объект куба все еще вращается, и, скажем, в настоящее время он находится на отметке 33,943 ..., пользователь может сделать еще одно событие касания, прежде чем эта анимация завершится.

Это событие касания сразу же снова вызовет метод -rotate. Происходит следующее: трансформации перекрываются, и изображение куба полностью растягивается и деформируется.

Таким образом, перед началом новой анимации текущая анимация должна быть остановлена.

UPDATE

Я вызываю это, прежде чем запустить анимацию:

- (void)resetAnimation {
    self.layer.transform = CATransform3DIdentity; // reset the transform to the identity transform ("no rotation applied, please")
    [Cube setAnimationDelegate:nil];
    [Cube setAnimationDidStopSelector:NULL];
}

Также я установил [Cube setAnimationBeginsFromCurrentState: YES]; везде, где я начинаю анимационный блок.

Итак, когда анимация запускается извне, это будет выглядеть так: (Обратите внимание, что на экране есть 5 объектов этого класса, которые можно активировать для анимации)

- (void)kickAnimation { // if that's called, the cube gets a kick to rotate
    self.layer.transform = CATransform3DIdentity;
    currentDegrees = 90; // just testing! it may also be negative
    NSString *animID = [NSString stringWithFormat:@"cube_%i",self.datasetID];
    if (currentDegrees > 0) {
        [self rotateRight:animID finished:0 context:self];
    } else if (currentDegrees < 0) {
        [self rotateLeft:animID finished:0 context:self];
    }
}

- (void)rotateRight:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    // 1) here the anchorPoint is set to the lower right corner
    // 2) here the view's frame is repositioned so that the cube doesn't move visually after the anchorPoint changed
    [self rotateByDegrees:currentDegrees animationID:animationID];
}

- (void)rotateByDegrees:(CGFloat)degrees animationID:(NSString *)animationID {
    [Cube beginAnimations:animationID context:self];
    [Cube setAnimationDelegate:self];
    [Cube setAnimationDidStopSelector:@selector(rotateBack:finished:context:)];
    [Cube setAnimationDuration:2.1f];
    [Cube setAnimationBeginsFromCurrentState:YES];
    CATransform3D rotatedTransform = self.layer.transform;
    rotatedTransform = CATransform3DRotate(rotatedTransform, degrees * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
    self.layer.transform = rotatedTransform;
    [UIView commitAnimations];
}

- (void)rotateBack:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    currentDegrees *= -1;
    [Cube beginAnimations:animationID context:self];
    self.layer.transform = CATransform3DIdentity;
    [Cube setAnimationDelegate:nil];
    [Cube setAnimationDidStopSelector:NULL];
    [Cube setAnimationDuration:2.1f];
    [Cube setAnimationBeginsFromCurrentState:YES];
    CATransform3D rotatedTransform = self.layer.transform;
    rotatedTransform = CATransform3DRotate(rotatedTransform, currentDegrees * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
    self.layer.transform = rotatedTransform;
    currentDegrees = 0;
    [UIView commitAnimations];
}

Теперь, похоже, почти работает. Куб больше не деформируется, если анимационные старты перекрываются. Но одна вещь все еще неправильна: если появляется новый «удар», и куб в настоящее время вращается назад, он должен немедленно начать вращаться вправо. Но бывает, что он сначала поворачивается назад, а затем распознает этот «удар», который выглядит довольно странно;)

Ответы [ 3 ]

5 голосов
/ 17 мая 2009

Здесь аналогичный вопрос и ответ.

Если вы позвоните [UIView setAnimationBeginsFromCurrentState:YES];, новая анимация начнется с того места, где находится вид, и остановит предыдущую анимацию.

3 голосов
/ 03 августа 2009

Если вы действительно хотите остановить все анимации, а затем перезапустить с указанными выше методами, то вызовите:

[self.layer removeAllAnimations];
2 голосов
/ 17 мая 2009

Как вы применяете преобразование? Я представляю что-то вроде этого:

- (void)rotate {
    [UIView beginAnimations:@"rotate" context:nil];
    self.transform = [self nextTargetTransform];
    [UIView commitAnimations];
}

Я не кодировал его для вашего примера куба, но это должно работать без проблем, с которыми вы сталкиваетесь. beginAnimations:context: должен признать, что вы уже преобразуете, и создать новое целевое состояние, которое плавно завершает преобразование. Разве этого не происходит?

Как я уже сказал, я не проверял вышеизложенное; Один возможный сбой заключается в том, что анимация неожиданно вернется к исходным настройкам и начнется снова. Если это произойдет, оставьте комментарий и немного больше кода, и мы разработаем исправление для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...