Как анимировать UIImageViews, такие как открытие дверей люка

Я пытаюсь создать анимацию, которая будет выглядеть как 2 французские двери (или 2 люка), открывающиеся в сторону пользователя.

Я попытался использовать встроенный переход UIViewAnimationOptionTransitionFlipFromRight, но источником перехода, похоже, является центр UIImageView, а не левый край. В основном у меня есть 2 UIImageViews, каждый из которых имеет экран. Я хотел бы, чтобы анимация выглядела так, как будто UIImageViews поднимаются от центра экрана к краям.

[UIView transitionWithView:leftView
                  duration:1.0
                   options:UIViewAnimationOptionTransitionFlipFromRight                           
                animations:^ { leftView.alpha = 0; }
                completion:^(BOOL finished) {
                    [leftView removeFromSuperview]; 
                }];

Кто-нибудь делал что-то подобное раньше? Любая помощь будет потрясающей!

ОБНОВЛЕНИЕ: рабочий код благодаря Нику Локвуду

leftView.layer.anchorPoint = CGPointMake(0, 0.5); // hinge around the left edge
leftView.frame = CGRectMake(0, 0, 160, 460); //reset view position

rightView.layer.anchorPoint = CGPointMake(1.0, 0.5); //hinge around the right edge
rightView.frame = CGRectMake(160, 0, 160, 460); //reset view position

[UIView animateWithDuration:0.75 animations:^{
    CATransform3D leftTransform = CATransform3DIdentity;
    leftTransform.m34 = -1.0f/500; //dark magic to set the 3D perspective
    leftTransform = CATransform3DRotate(leftTransform, -M_PI_2, 0, 1, 0);
    leftView.layer.transform = leftTransform;

    CATransform3D rightTransform = CATransform3DIdentity;
    rightTransform.m34 = -1.0f/500; //dark magic to set the 3D perspective
    rightTransform = CATransform3DRotate(rightTransform, M_PI_2, 0, 1, 0);
    rightView.layer.transform = rightTransform;
}];

person wes    schedule 04.02.2012    source источник
comment
Примечание: вы можете поменять местами знак минус при повороте двери влево и вправо, чтобы двери открывались внутрь.   -  person Nick Lockwood    schedule 04.02.2012


Ответы (1)


Сначала добавьте в проект библиотеку QuartzCore и #import <QuartzCore/QuartzCore.h>

Каждое представление имеет свойство layer с подсвойствами, которые можно анимировать. Здесь вы найдете все действительно классные вещи, когда дело доходит до возможностей анимации (советую прочитать о свойствах класса CALayer, которые вы можете установить — это поразит вас — динамические мягкие тени на любом виде?)

Впрочем, вернемся к теме. Чтобы открыть двери в 3D, сначала расположите их так, как если бы они были закрыты, чтобы каждая дверь занимала половину экрана.

Теперь установите их свойства view.layer.anchorPoint следующим образом.

leftDoorView.layer.anchorPoint = CGPoint(0, 0.5); // hinge around the left edge
rightDoorView.layer.anchorPoint = CGPoint(1.0, 0.5); // hinge around the right edge

Теперь примените следующую анимацию

[UIView animateWithDuration:0.5 animations:^{
   CATransform3D leftTransform = CATransform3DIdentity;
   leftTransform.m34 = -1.0f/500; //dark magic to set the 3D perspective
   leftTransform = CATransform3DRotate(leftTransform, M_PI_2, 0, 1, 0); //rotate 90 degrees about the Y axis
   leftDoorView.layer.transform = leftTransform;
   //do the same thing but mirrored for the right door, that probably just means using -M_PI_2 for the angle. If you don't know what PI is, Google "radians"
}];

И это должно сделать это.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: я на самом деле не проверял это, поэтому углы могут быть обратными, а перспектива может быть странной и т. д., но это должно быть хорошим началом, по крайней мере.

ОБНОВЛЕНИЕ: Любопытство взяло верх надо мной. Вот полностью рабочий код (предполагается, что левая и правая двери выложены в закрытом положении в nib-файле):

- (void)viewDidLoad
{
    [super viewDidLoad];

    leftDoorView.layer.anchorPoint = CGPointMake(0, 0.5); // hinge around the left edge
    leftDoorView.center = CGPointMake(0.0, self.view.bounds.size.height/2.0); //compensate for anchor offset
    rightDoorView.layer.anchorPoint = CGPointMake(1.0, 0.5); // hinge around the right edge
    rightDoorView.center = CGPointMake(self.view.bounds.size.width,self.view.bounds.size.height/2.0); //compensate for anchor offset
}

- (IBAction)open
{
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = -1.0f/500;
    leftDoorView.layer.transform = transform;
    rightDoorView.layer.transform = transform;

    [UIView animateWithDuration:0.5 animations:^{

        leftDoorView.layer.transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
        rightDoorView.layer.transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);
    }];
}

- (IBAction)close
{
    [UIView animateWithDuration:0.5 animations:^{

        CATransform3D transform = CATransform3DIdentity;
        transform.m34 = -1.0f/500;
        leftDoorView.layer.transform = transform;
        rightDoorView.layer.transform = transform;
    }];
}
person Nick Lockwood    schedule 04.02.2012
comment
темная магия звучала лучше, чем мне не хочется сейчас объяснять матрицы ;-) - person Nick Lockwood; 04.02.2012
comment
На самом деле, я должен был сказать, что никому нельзя рассказывать, что такое Матрица... - person Nick Lockwood; 04.02.2012
comment
Классное начало спасибо. Я изучаю это больше. Тем временем произошла ошибка с вызовом CATransform3DMakeRotation, который принимает только 4 аргумента. Я удалил «0» в конце и изменил первый параметр на leftTransform.m34. Это звучит разумно? Это создает странную мгновенную трансформацию без анимации. - person wes; 04.02.2012
comment
А, ну ладно. Я думаю, что на самом деле это метод CATransform3DRotate, верно. Я до сих пор не вижу никакой анимации, но я продолжу копать. - person wes; 04.02.2012
comment
Думаю, я понял. У меня левая дверь работает. Должен ли я опубликовать свой рабочий код под своим вопросом? (а затем отдать вам должное, конечно)! Ты спасатель - person wes; 04.02.2012
comment
Ударь тебя! Все равно выкладывайте свои - будет интересно сравнить и сопоставить. - person Nick Lockwood; 04.02.2012