iOS實現透視效果

需求:通過 layer 層,實現透視效果。

參考地址:http://geeklu.com/2012/07/ios-3d-perspective/http://blog.sina.com.cn/s/blog_71715bf801019ut9.html

先看一下原始界面:


經過 rotate 之後:

- (void)viewDidLoad
{
    [superviewDidLoad];
    
    CATransform3D rotate = CATransform3DMakeRotation(M_PI/3, 1, 0, 0);
    _imageView.layer.transform = rotate;
}


可以看到,iOS 自帶的方法中,是通過做正交投影做的 rotate。

通過下面的方法,可以實現透視投影的效果:

CATransform3D CATransform3DMakePerspective(CGPoint center, float disZ)
{
    CATransform3D transToCenter = CATransform3DMakeTranslation(-center.x, -center.y, 0);
    CATransform3D transBack = CATransform3DMakeTranslation(center.x, center.y, 0);
    CATransform3D scale = CATransform3DIdentity;
    scale.m34 = -1.0f/disZ;
    return CATransform3DConcat(CATransform3DConcat(transToCenter, scale), transBack);
}
CATransform3D CATransform3DPerspect(CATransform3D t, CGPoint center, float disZ)
{
    return CATransform3DConcat(t, CATransform3DMakePerspective(center, disZ));
} 

CATransform3DPerspect 的作用:(摘自 http://blog.sina.com.cn/s/blog_71715bf801019ut9.html

這個函數的實現原理要參考計算機圖形學的3D變換部分。接口的含義,center指的是相機的位置,相機的位置是相對於要進行變換的CALayer的來說的,原點是CALayer的anchorPoint在整個CALayer的位置,例如CALayer的大小是(100, 200), anchorPoint值爲(0.5, 0.5),此時anchorPoint在整個CALayer中的位置就是(50, 100),正中心的位置。傳入透視變換的相機位置爲(0, 0),那麼相機所在的位置相對於CALayer就是(50, 100)。如果希望相機在左上角,則需要傳入(-50, -100)。disZ表示的是相機離z=0平面(也可以理解爲屏幕)的距離。

CATransform3DPerspect 的使用:

- (void)viewDidLoad
{
    [superviewDidLoad];
    
    CATransform3D rotate = CATransform3DMakeRotation(M_PI/3, 1, 0, 0);
    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(0, 0), 200);
}

效果圖:


現在上面的方法實現了透視效果,接着還需要解決另外兩個問題:

  • 如何以視圖的最下方的邊爲軸旋轉
  • 透視效果不要那麼明顯

先來看一下如何設置透視效果的強弱

參考:http://geeklu.com/2012/07/ios-3d-perspective 

           http://blog.sina.com.cn/s/blog_620bf89501011fl8.html 

           http://blog.sina.com.cn/s/blog_620bf89501011g7n.html


由上面的信息可知,將 z 值設置大一些,這透視效果就相對弱一些,如將 z 設置爲 1000

- (void)viewDidLoad
{
    [superviewDidLoad];
    
    CATransform3D rotate = CATransform3DMakeRotation(M_PI/3, 1, 0, 0);
    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(0, 0), 1000);
}

效果圖如下


要實現繞固定邊旋轉,只需要調整 layer 的 anchorPoint 就行了

- (void)viewDidLoad
{
    [superviewDidLoad];
    
    CALayer *layer = [_imageView layer];
    CGPoint oldAnchorPoint = layer.anchorPoint;
    [layer setAnchorPoint:CGPointMake(0.5, 1.0)];
    [layer setPosition:CGPointMake(layer.position.x + layer.bounds.size.width * (layer.anchorPoint.x - oldAnchorPoint.x), layer.position.y + layer.bounds.size.height * (layer.anchorPoint.y - oldAnchorPoint.y))];
    
    CATransform3D rotate = CATransform3DMakeRotation(M_PI/3, 1, 0, 0);
    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(0, 0), 1000);
} 


下面再把 disZ 設置爲 100,看看效果


上圖中的圖片繞着底邊旋轉了 60 度,按照勾股定理,上面的邊應該是靠在綠色的邊上的,但爲什麼差這麼多呢?看一下下面這張圖:


由於我移動了 anchorPoint,如上圖,現在的觀察點在 eye1 上面。以 yz 面上的點爲例,在 eye2 處,紅色矩形在 xy 面上的投影爲 A 點,這也就是爲什麼旋轉之後,矩形在綠色線條下面的原因了。ok,現在把 eye1 往上移動到視圖中心即可。

- (void)viewDidLoad
{
    [superviewDidLoad];
    
    CALayer *layer = [_imageView layer];
    CGPoint oldAnchorPoint = layer.anchorPoint;
    [layer setAnchorPoint:CGPointMake(0.5, 1)];
    [layer setPosition:CGPointMake(layer.position.x + layer.bounds.size.width * (layer.anchorPoint.x - oldAnchorPoint.x), layer.position.y + layer.bounds.size.height * (layer.anchorPoint.y - oldAnchorPoint.y))];
    
    CATransform3D rotate = CATransform3DMakeRotation(M_PI/180.0*60.0, 1, 0, 0);
    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(0, -90), 100);
}



轉載自:http://fred.easymorse.com/?p=1400

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章