Как мне складывать изображения для имитации глубины с помощью Core Animation? - PullRequest
6 голосов
/ 14 мая 2010

У меня есть серия UIImages, с которыми мне нужно имитировать глубину. Я не могу использовать масштабирование, потому что мне нужно иметь возможность вращать родительский вид, и изображения должны выглядеть так, будто они визуально сложены друг напротив друга, а не в одной плоскости.

Я создал новый проект на основе ViewController и поместил его в viewDidLoad (а также прикрепил три изображения размером 120x120 пикселей с именами 1.png, 2.png и 3.png):

- (void)viewDidLoad {

    // display image 3
    UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]];
    three.center = CGPointMake(160 + 60, 240 - 60);
    [self.view addSubview:three];

    // rotate image 3 around the z axis
    // THIS IS INCORRECT
    CATransform3D theTransform = three.layer.transform;
    theTransform.m34 = 1.0 / -1000;
    three.layer.transform = theTransform;

    // display image 2
    UIImageView *two = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.png"]];
    two.center = CGPointMake(160, 240);
    [self.view addSubview:two];

    // display image 1
    UIImageView *one = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.png"]];
    one.center = CGPointMake(160 - 60, 240 + 60);
    [self.view addSubview:one];

    //  rotate image 3 around the z axis
    // THIS IS INCORRECT
    theTransform = one.layer.transform;
    theTransform.m34 = 1.0 / 1000;
    one.layer.transform = theTransform;

    // release the images
    [one release];
    [two release];
    [three release];

    // rotate the parent view around the y axis
    theTransform = self.view.layer.transform;
    theTransform.m14 = 1.0 / -500;
    self.view.layer.transform = theTransform;

    [super viewDidLoad];
}

У меня есть очень конкретные причины, по которым я не использую EAGLView и почему я не загружаю изображения как CALayers (т.е. почему я использую UIImageViews для каждого из них). Это всего лишь небольшая демонстрация, которую я могу использовать, чтобы точно определить, что мне нужно в моем родительском приложении.

Есть ли какой-нибудь матричный способ перевода этих 2-мерных изображений вдоль оси z, чтобы они выглядели так, как я пытаюсь представить? Я просмотрел другие статьи StackOverflow, а также ссылки на Википедию и не нашел того, что искал, хотя, возможно, не обязательно использовал правильные термины для того, что я пытаюсь сделать.

Ответы [ 2 ]

7 голосов
/ 14 мая 2010

Чтобы сложить ваши виды и применить к ним перспективу, вам нужно сначала разместить их в разных позициях Z, а затем применить эффект перспективы к содержащему слою.

Я полагаю, что следующий код сделает это, но я не проверял это (я делал нечто подобное с чистыми CALayers, поэтому общие принципы верны):

- (void)viewDidLoad {

    UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]];
    three.center = CGPointMake(160 + 60, 240 - 60);
    [self.view addSubview:three];

    three.layer.zPosition = -100;

    UIImageView *two = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.png"]];
    two.center = CGPointMake(160, 240);
    [self.view addSubview:two];

    two.layer.zPosition = 0;

    UIImageView *one = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.png"]];
    one.center = CGPointMake(160 - 60, 240 + 60);
    [self.view addSubview:one];

    one.layer.zPosition = 100;

    // release the images
    [one release];
    [two release];
    [three release];

    CATransform3D theTransform = self.view.layer.sublayerTransform;
    theTransform.m34 = 1.0 / -500;
    self.view.layer.sublayerTransform = theTransform;

    [super viewDidLoad];
}

В вашем коде вы устанавливаете только соответствующую часть CATransform3D на каждом уровне представления (это то, что делает компонент m34 матрицы CATransform3D). Вы на самом деле не перемещаете их в плоскости Z. Вы можете использовать преобразование для этого, но я обнаружил, что свойство zPosition ваших CALayers обеспечивает более чистый способ определения расположения слоев в 3-D.

После того, как вы разместили слои относительно друг друга (с отрицательными значениями, уходящими от точки зрения пользователя), вам нужно применить эффект перспективы ко всем слоям, размещенным в вашем главном представлении. Для этого я считаю, что установка sublayerTransform слоя представления хостинга необходима для правильного применения перспективы ко всем размещенным слоям.

Если вы хотите повернуть серию изображений, используйте CATransform3DRotate() в подслоеПреобразование слоя основного вида хостинга.

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

2 голосов
/ 30 мая 2010

Я наконец решил эту проблему с помощью CATransform3DMakeTranslation, который, кажется, является единственным способом перемещения слоя вверх или вниз по оси z:

UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]];
three.layer.transform = CATransform3DMakeTranslation(0.0f, 0.0f, 20.0f);
three.center = CGPointMake(160 + 60, 240 - 60);
[self.view addSubview:three];

(Я также переместил UIImageView на -20.0f пикселей по оси z. Это, наконец, дало искомый эффект.)

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