Как анимировать UIImageViews, такие как открытие дверей люка - PullRequest
14 голосов
/ 04 февраля 2012

Я пытаюсь создать анимацию, которая будет выглядеть как 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;
}];

1 Ответ

26 голосов
/ 04 февраля 2012

Сначала добавьте библиотеку 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"
}];

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

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

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

- (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;
    }];
}
...