2012-09-25 135 views
1

我在CALayer的子類中使用這個代碼,這些實例是根CALayer的子層。如何翻轉CALayer圍繞其Y軸?

-(void)setSelected:(bool)s { 
    selected=s; 
    if (s) 
    { 
     CATransform3D rot = CATransform3DMakeRotation(M_PI, 0, 1, 0); 
     rot.m34=-1.0/200; 
     [self setTransform:rot]; 

    } 
    else 
    { 
      CATransform3D rot = CATransform3DMakeRotation(0, 0, 1, 0); 
     rot.m34=-1.0/200; 
     [self setTransform:rot]; 
    } 
} 

當所選擇的屬性設置爲TRUE時,會出現以下情況:轉動完成,直到角度等於M_PI/2,則該層會消失,因爲它是正交的。動畫的結尾是錯誤的:在動畫的第一部分(例如在左側)中出現的邊緣,在左側而不是在右側結束動畫。但內容翻轉。

我認爲這與兩個旋轉矩陣之間的插值有關,但我無法準確理解發生了什麼。

詳情:動畫看起來是這樣做的:

  1. 通過周圍+ PI/2 Y軸旋轉增量
  2. 內容由-Pi/2左右翻轉Y軸
  3. 增量旋轉,就好像它反彈了(yz)飛機

翻轉的內容是我想要實現的。

這裏是我得到的動畫幀。如你所見,梯形的小邊總是在左邊;它應該在動畫結尾的右側(右上框)。 A layer rotating around the Y-axis

+0

問題是什麼?內容是翻轉的嗎?或者是翻轉角度還是翻轉方向? –

回答

6

變換的數學不正確。您應該在旋轉變換之後應用透視變換,這意味着將兩個變換連接起來。更改旋轉變換的m34係數並不等效。

您應該通過以下替換代碼:

-(void)setSelected:(bool)s { 
    selected=s; 
    CATransform3D perpectiveTransform = CATransform3DIdentity; 
    perpectiveTransform.m34 =-1.0/200; 

    if (s) 
    { 

     CATransform3D rot = CATransform3DMakeRotation(M_PI, 0, 1, 0); 
     [self setTransform:CATransform3DConcat(rot, perpectiveTransform)]; 

    } 
    else 
    { 
     CATransform3D rot = CATransform3DMakeRotation(0, 0, 1, 0); 
     [self setTransform:CATransform3DConcat(rot, perpectiveTransform)]; 
    } 
} 

順便說一句,以應用透視的往往更方便的方法轉換是使用superlayer的sublayerTransform屬性,從而將其應用到每個子層(如果這是需要的)。

這會產生這樣的:

self.superlayer.sublayerTransform = perspectiveTransform; //do this in your setup 
.... 
self.transform = rot; 

對於相同的期待的結果。

+0

第二種方法也是可行的,但在我的情況下,它不工作,因爲我只是想讓每個圖層在其自己的空間中執行3D旋轉,看起來完全相同(由於空間中的位置而不會變形)。我有一個橡皮筋來選擇這些也是CALayer的圖層。設置這種轉換也會轉換橡皮筋,如果我想用它們來繪製選擇橡皮筋,那麼視圖內的鼠標點擊位置也需要未被投影。 – alecail

-1

想象一下,您的圖層是一塊平面半透明塑料,並且圖像投射到其上,因此它透過兩側。在pi/2的旋轉時,它是邊緣開啓的,所以它消失了。當你的轉動大於pi/2但小於pi時,塑料片的背面露出來。由於它是半透明的,因此您可以看到圖像的背面,但由於您從背面看到它,所以它是鏡像的。當角度達到pi時,紙張在y軸上翻轉180度。它是顛倒的,你可以從後面看到圖像,所以它是倒退的。

5

如果有人只是想翻轉圖像的或視圖的方向水平

yourView.layer.transform = CATransform3DMakeScale(-1, 1, 1); 

yourView.layer.affineTransform = CGAffineTransformMakeScale(-1, 1);