现在的位置: 首页 > 综合 > 正文

iOS实现透视效果

2018年05月05日 ⁄ 综合 ⁄ 共 3276字 ⁄ 字号 评论关闭

需求:通过 layer 层,实现透视效果。

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

先看一下原始界面:

IOS Simulator Screen shot May 5 2013 8 50 42 PM

经过 rotate 之后:

- (void)viewDidLoad

{

    [superviewDidLoad];

    

    CATransform3D rotate
CATransform3DMakeRotation(M_PI/3100);

    _imageView.layer.transform =
rotate;

}

IOS Simulator Screen shot May 5 2013 8 50 52 PM

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

通过下面的方法,可以实现透视投影的效果:

CATransform3D CATransform3DMakePerspective(CGPoint center, float disZ)

{

    CATransform3D transToCenter = CATransform3DMakeTranslation(-center.x,
-center.y0);

    CATransform3D transBack = CATransform3DMakeTranslation(center.x,
center.y0);

    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/3100);

    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(00), 200);

}

 

效果图:

IOS Simulator Screen shot May 5 2013 8 51 02 PM

现在上面的方法实现了透视效果,接着还需要解决另外两个问题:

  • 如何以视图的最下方的边为轴旋转
  • 透视效果不要那么明显

先来看一下如何设置透视效果的强弱

参考: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

7525866072 efebf5cd22

由上面的信息可知,将 z 值设置大一些,这透视效果就相对弱一些,如将 z 设置为 1000

- (void)viewDidLoad

{

    [superviewDidLoad];

    

    CATransform3D rotate
CATransform3DMakeRotation(M_PI/3100);

    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(00), 1000);

}

效果图如下

IOS Simulator Screen shot May 7 2013 12 13 07 AM

要实现绕固定边旋转,只需要调整 layer 的 anchorPoint 就行了

- (void)viewDidLoad

{

    [superviewDidLoad];

    

    CALayer *layer = [_imageView layer];

    CGPoint oldAnchorPoint = layer.anchorPoint;

    [layer setAnchorPoint:CGPointMake(0.51.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/3100);

    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(00), 1000);

IOS Simulator Screen shot May 7 2013 10 54 50 PM

下面再把 disZ 设置为 100,看看效果

IOS Simulator Screen shot May 10 2013 12 14 01 AM

上图中的图片绕着底边旋转了 60 度,按照勾股定理,上面的边应该是靠在绿色的边上的,但为什么差这么多呢?看一下下面这张图:

Blank 2

由于我移动了 anchorPoint,如上图,现在的观察点在 eye1 上面。以 yz 面上的点为例,在 eye2 处,红色矩形在 xy 面上的投影为 A 点,这也就是为什么旋转之后,矩形在绿色线条下面的原因了。ok,现在把 eye1 往上移动到视图中心即可。

- (void)viewDidLoad

{

    [superviewDidLoad];

    

    CALayer *layer = [_imageView layer];

    CGPoint oldAnchorPoint = layer.anchorPoint;

    [layer setAnchorPoint:CGPointMake(0.51)];

    [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.0100);

    _imageView.layer.transform = CATransform3DPerspect(rotate, CGPointMake(0,
-90), 100);

}

IOS Simulator Screen shot May 10 2013 12 14 24 AM

抱歉!评论已关闭.