Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this transformation using CATransform3D reducing the view's width?

Take a look at the following progression of images:

enter image description hereenter image description hereenter image description here

What's happening here is first I selected "Baseball", causing the 3 gray views you see to rotate left so that the one with the various levels is in the middle (second image). You can see that already at this point the view's width has been substantially reduced. The third image occurs after clicking on the view containing the sports names, causing it to rotate back to the middle.

From what I can tell, the width of a view is reduced when it rotates into the middle. But I have no idea why.

Here's the relevant code. pos refers to where the view in question is going to be located. 0 indicates that it's in the middle, 1 indicates that it is one to the right of the middle, -1 is one to the left of the middle, etc.

- (void)perspectiveView:(MenuSection *)view forPosition:(NSInteger)pos
{

    CALayer *layer = view.layer;
    CATransform3D transform = CATransform3DIdentity;

    MenuSection *prevView = (pos >= 0) ? (MenuSection *)[self viewWithTag:view.tag - 1] : (MenuSection *)[self viewWithTag:view.tag + 1];

    if (pos == 0) {
        view.changingToFrame = CGRectMake(round((480 - view.frame.size.width)/2), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
        view.frame = view.changingToFrame;

    } else {

        if (pos == 1) {
            NSLog(@"%@",NSStringFromCGRect(prevView.changingToFrame));
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x + prevView.frame.size.width + 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / 1000;
        } else if (pos == -1){
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x - view.frame.size.width - 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / -1000;
        } else if (pos == 2){
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x + prevView.frame.size.width + 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / 500;
        } else if (pos == -2){
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x - view.frame.size.width - 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / -500;
        }

        view.frame = view.changingToFrame;

        transform = CATransform3DRotate(transform, 45.0f * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
    }

    layer.transform = transform;
}
like image 607
maxedison Avatar asked Jan 17 '12 02:01

maxedison


1 Answers

I've solved it. Turns out that applying CATransform3D actually changes the frame of the view. In the code I posted, when I set the new frame of the view (because it rotates into a different position), I simply use view.frame.size.width in CGRectMake() in an attempt to maintain the width. BUT, since the CATransform3D had previously modified the width, I don't get the actual width the I want.

The solution was to subclass the necessary UIViews and store their original frame in an ivar. That way, I can always use that as the reference point when moving the views to different positions.

like image 57
maxedison Avatar answered Nov 15 '22 08:11

maxedison