AVPlayerLayer是一个CALayer的subclass,它是属于另一个framework,AVFoundation framework。它主要用来在iOS中播放视频内容,实际上,例如MPMoviePlayer里面的底层播放实现用的都是它。使用起来很简单,1、创建实例;2、播放操作
我们可以用下面这个简单的例子演示一下这个的用法
- (void)testPlayerLayer { UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; containerView.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds)); [self.view addSubview:containerView]; // get video url NSURL *url = [[NSBundle mainBundle] URLForResource:@"Ship" withExtension:@"mp4"]; // Create player and player layer, need <AVFoundation/AVFoundation.h> AVPlayer *player = [AVPlayer playerWithURL:url]; AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; // Set player frame and attach to our view playerLayer.frame = containerView.bounds; [containerView.layer addSublayer:playerLayer]; [player play]; }
效果就如下图所示
使用方法就是这样,在这里要说的是,AVPlayerLayer既然是一个CALayer的subclass,那么我们就可以像对待一个普通的CALayer来对待它,使用CALayer的一些方法,比如transform,roundedCorner这些效果都可以加在它上面,还是用例子说话。
- (void)test3DPlayerLayer { UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; containerView.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds)); [self.view addSubview:containerView]; // get video url NSURL *url = [[NSBundle mainBundle] URLForResource:@"Ship" withExtension:@"mp4"]; // Create player and player layer, need <AVFoundation/AVFoundation.h> AVPlayer *player = [AVPlayer playerWithURL:url]; AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; // Set player frame and attach to our view playerLayer.frame = containerView.bounds; [containerView.layer addSublayer:playerLayer]; // Transform layer CATransform3D transform = CATransform3DIdentity; transform.m34 = -1.0 / 500.0f; transform = CATransform3DRotate(transform, M_PI_4, 1, 1, 0); playerLayer.transform = transform; // Add rounded corners and border playerLayer.masksToBounds = YES; playerLayer.cornerRadius = 20.0f; playerLayer.borderColor = [UIColor redColor].CGColor; playerLayer.borderWidth = 5.0f; [player play]; }
经过3D变换,加圆角,加边框后的效果如下
代码不难,不过我要解释一下下面这几句关于3D变换的操作
CATransform3D transform = CATransform3DIdentity; transform.m34 = -1.0 / 500.0f; transform = CATransform3DRotate(transform, M_PI_4, 1, 1, 0); playerLayer.transform = transform;
3D变换在iOS中是通过使用矩阵乘法运算来得出最终各个坐标点的,原理是下面的图
矩阵乘法是怎么运算的就不在这里讲了,网上很容易找到,另外就是在iOS设备上xyz各个轴的定义,以及如何围绕的轴来旋转
在iOS提供的transform的API中,不需要我们直接来进行矩阵运算,只需要我们指定旋转所需要的参数,其中有角度(单位是弧度),以及是按照哪个轴进行旋转。常用的有下面两个函数
CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0); transform = CATransform3DRotate(transform, M_PI_4, 1, 1, 0);
第一个函数是从基本面开始,进行的绝对值旋转,4个参数,分别代表了角度,x,y,z,这里是按照y轴旋转了PI/4, PI是180度,也就是相当于旋转了45度,x和z的值为0,也就是不旋转的意思。第二个函数是在第一个transform的基础上继续进行旋转,旋转是既在x轴旋转,也在y轴旋转。
如果大家实验一下,发现其实旋转后的效果怪怪得,
比如只执行第一个函数的话,可能觉得图片仅仅变窄了(旋转前的原图是个正方形),看不出有旋转的感觉。这是因为没有使用Perspective Projection的原因,Perspective Projection在用户看来,应该是离我们近的,会大一些,离我们远得的看上去会比较小才正确。这个效果是否体现出来,其实是由矩阵中的m34值来决定的
也就是红圈圈里面的那个,这个值可以设置为 -1/d,d是相当于我们的眼睛与图片的距离,一般来说,对于iOS的应用,我们使用的d值的范围在500~1000之间,值越小,效果越明显,越大,效果越不明显,我们可以看一下m34的设置和使用方法
CATransform3D transform = CATransform3DIdentity; //apply perspective transform.m34 = - 1.0 / 500.0; //rotate by 45 degrees along the Y axis transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0); //apply to layer self.layerView.layer.transform = transform;
这回效果出来了吧!
CATransform3DIdentity,这个值在矩阵运算中,相当于什么都没干,也就是说,任意一个坐标跟CATransform3DIdentity做乘法运算时,计算后的结果不会变化。
有了这些说明,文章中第一个例子的各条语句在理解上应该都没有问题了。