2012-01-04 55 views
3

真的很感激任何幫助這一個。我在視圖上應用了三維變換,並需要確定渲染視圖的邊緣座標,以便可以呈現與其相鄰的另一個視圖(沒有任何像素間隙)。具體而言,我想通過動畫角度將一系列視圖(「頁面」)摺疊成小冊子。iOS的CATransform3D座標

int dir = (isOddNumberedPage ? 1 : -1); 
    float angle = 10.0; 

    theView.frame = CGRectMake(pageNumber * 320, 0, 320, 460);   
    CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; 
    rotationAndPerspectiveTransform.m34 = -1.0/2000; // Perspective 
    rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 
      dir * angle/(180.0/M_PI), 0.0f, 1.0f, 0.0f); 
    theView.layer.transform = rotationAndPerspectiveTransform; 

    // Now need to get the top, left, width, height of the transformed view to correct the view's left offset 

我已經嘗試了一些通過檢查CALayer的,在使用一些矩陣數學代碼段,我發現一個失敗的嘗試這樣做的方法,但一直沒能破解它,甚至接近(視角度,出好20個像素)。有沒有一種方法可以做到這一點,而不用花2周時間閱讀矩陣數學教科書?

回答

5

視圖的框架是超視圖座標系中與軸對齊的矩形。框架完全包圍視圖的邊界。如果視圖被轉換,框架會調整以緊密包圍視圖的新邊界。

當您將Y軸旋轉和透視應用於視圖時,視圖的左右邊緣會移向其錨點(通常爲視圖的中心)。左邊緣也可以長或短,而右邊緣則相反。

因此,視圖的框架(應用轉換後)將爲您提供轉換視圖的左邊緣座標和寬度,以及較高邊的頂部和高度(可能是左邊或右邊)。這裏是我的測試代碼:

NSLog(@"frame before tilting = %@", NSStringFromCGRect(self.tiltView.frame)); 
float angle = 30.0; 
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; 
rotationAndPerspectiveTransform.m34 = -1.0/2000; // Perspective 
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 
     1 * angle/(180.0/M_PI), 0.0f, 1.0f, 0.0f); 
self.tiltView.layer.transform = rotationAndPerspectiveTransform; 
NSLog(@"frame after tilting = %@", NSStringFromCGRect(self.tiltView.frame)); 

下面是輸出:

2012-01-04 12:44:08.405 layer[72495:f803] frame before tilting = {{50, 50}, {220, 360}} 
2012-01-04 12:44:08.406 layer[72495:f803] frame after tilting = {{62.0434, 44.91}, {190.67, 370.18}} 

您也可以獲取視圖的角的座標,在上海華的使用convertPoint:fromView:convertPoint:toView:座標空間。測試代碼:

CGRect bounds = self.tiltView.bounds; 
    CGPoint upperLeft = bounds.origin; 
    CGPoint upperRight = CGPointMake(CGRectGetMaxX(bounds), bounds.origin.y); 
    CGPoint lowerLeft = CGPointMake(bounds.origin.x, CGRectGetMaxY(bounds)); 
    CGPoint lowerRight = CGPointMake(upperRight.x, lowerLeft.y); 
#define LogPoint(P) NSLog(@"%s = %@ -> %@", #P, \ 
    NSStringFromCGPoint(P), \ 
    NSStringFromCGPoint([self.tiltView.superview convertPoint:P fromView:self.tiltView])) 
    LogPoint(upperLeft); 
    LogPoint(upperRight); 
    LogPoint(lowerLeft); 
    LogPoint(lowerRight); 

輸出:

2012-01-04 13:03:00.663 layer[72635:f803] upperLeft = {0, 0} -> {62.0434, 44.91} 
2012-01-04 13:03:00.663 layer[72635:f803] upperRight = {220, 0} -> {252.713, 54.8175} 
2012-01-04 13:03:00.663 layer[72635:f803] lowerLeft = {0, 360} -> {62.0434, 415.09} 
2012-01-04 13:03:00.663 layer[72635:f803] lowerRight = {220, 360} -> {252.713, 405.182} 

注意的Y upperLeft和upperRight點的座標是上海華盈的座標系中的不同。

+0

感謝羅布 - 你是一位絕對的明星。花了幾分鐘讓它在我的場景中工作,但你的解釋是現貨,所以讓我在那裏。 – Phil 2012-01-05 13:46:46