在iOS利用动画实现全景视图

来源:互联网 发布:乐乎社区是什么意思 编辑:程序博客网 时间:2024/06/05 22:52

干货,干货,这个绝对是干货,研究了很久,参考了网上的代码,终于明白了如何利用CATransform3D实现一个全景的观看模式。

整个全景类的项目有两个难点,一是搭建一个正方体的场景,二是通过滑动改变观看的视角

如何搭建一个正方体的场景呢,我们使用CATransform3D里面的透视动画制作

代码如下:

    //image1(前)    //获取一个标准默认的CATransform3D仿射变换矩阵CATransform3D transform3D = CATransform3DIdentity;    //image与六面体中心的角度为(0,0)(hAngel为点与水平位置的角度,vAngle为点与竖直位置的角度。CGFloat tempHAngle=_hAngle;CGFloat tempVAngle=_vAngle;    //初始化transform3D = CATransform3DIdentity;    //透视效果    /*     CGFloat m11(x缩放), m12(y切变), m13(旋转), m14();     CGFloat m21(x切变), m22(y缩放), m23(), m24();     CGFloat m31(旋转), m32(), m33(), m34(透视效果,要操作的这个对象要有旋转的角度,否则没有效果。正直/负值都有意义);     CGFloat m41(x平移), m42(y平移), m43(z平移), m44();          m34的默认值是0,我们可以通过设置m34为-1.0 / d来应用透视效果,d代表了想象中视角相机和屏幕之间的距离     */    transform3D.m34 = 1 / -_zoomFactor;        //_referenceSide中心点size        /*     对于tz来说,值越大,那么图层就越往外(接近屏幕),值越小,图层越往里(屏幕里)。          CATransform3D CATransform3DTranslate (CATransform3D t, CGFloat tx, CGFloat ty, CGFloat tz);          在某个transform3D变换的基础上进行平移变换,t是上一个transform3D,tx,ty,tz对应x,y,z轴的平移          */        //(obj,-referenceSide,0,0),平移transform3D=CATransform3DTranslate(transform3D,   _referenceSide*sin(-tempHAngle),   -_referenceSide*cos(-tempHAngle)*sin(-tempVAngle),   -(_referenceSide*cos(-tempHAngle)*cos(-tempVAngle)-_zoomFactor)   );    /*     angle参数是旋转的角度,为弧度制 0-2π     x,y,z决定了旋转围绕的中轴,取值为-1——1之间,例如(1,0,0),则是绕x轴旋转(0.5,0.5,0),则是绕x轴与y轴中间45度为轴旋转,依次进行计算     CATransform3D CATransform3DMakeRotation (CGFloat angle, CGFloat x, CGFloat y, CGFloat z);          在一个transform3D的基础上进行旋转变换,其他参数如上          CATransform3D CATransform3DRotate (CATransform3D t, CGFloat angle, CGFloat x, CGFloat y, CGFloat z);          */    //绕y轴旋转0度transform3D=CATransform3DRotate(transform3D, tempHAngle, 0, 1, 0);    if (_imageOver1.image != nil) _imageOver1.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));    //将3D信息赋值给image_image1.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));            //iamge2(右)    //image2与六面体中心的角度为(-PI/2,0)(hAngel为点与水平位置的角度,vAngle为点与竖直位置的角度。tempHAngle=_hAngle-(M_PI/2);tempVAngle=_vAngle;transform3D = CATransform3DIdentity;    transform3D.m34 = 1 / -_zoomFactor;    //(obj,referenceside,0,0)transform3D=CATransform3DTranslate(transform3D,   _referenceSide*sin(-tempHAngle),   -_referenceSide*cos(-tempHAngle)*sin(-tempVAngle),   -(_referenceSide*cos(-tempHAngle)*cos(-tempVAngle)-_zoomFactor)   );    //绕y轴旋转-90度transform3D=CATransform3DRotate(transform3D, tempHAngle, 0, 1, 0);    if (_imageOver2.image != nil) _imageOver2.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));_image2.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));        //image3(后)    //image3与六面体中心的角度为(-PI,0)(hAngel为点与水平位置的角度,vAngle为点与竖直位置的角度。tempHAngle=_hAngle-(M_PI);tempVAngle=_vAngle;transform3D = CATransform3DIdentity;    transform3D.m34 = 1 / -_zoomFactor;transform3D=CATransform3DTranslate(transform3D,   _referenceSide*sin(-tempHAngle),   -_referenceSide*cos(-tempHAngle)*sin(-tempVAngle),   -(_referenceSide*cos(-tempHAngle)*cos(-tempVAngle)-_zoomFactor)   );transform3D=CATransform3DRotate(transform3D, tempHAngle, 0, 1, 0);    if (_imageOver3.image != nil) _imageOver3.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));_image3.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));    //image4(左)    //image4与六面体中心的角度为(-3*PI/2,0)(hAngel为点与水平位置的角度,vAngle为点与竖直位置的角度。    tempHAngle=_hAngle-(3*M_PI/2);tempVAngle=_vAngle;transform3D = CATransform3DIdentity;    transform3D.m34 = 1 / -_zoomFactor;transform3D=CATransform3DTranslate(transform3D,   _referenceSide*sin(-tempHAngle),   -_referenceSide*cos(-tempHAngle)*sin(-tempVAngle),   -(_referenceSide*cos(-tempHAngle)*cos(-tempVAngle)-_zoomFactor)   );    //绕y轴旋转180transform3D=CATransform3DRotate(transform3D, tempHAngle, 0, 1, 0);    if (_imageOver4.image != nil) _imageOver4.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));_image4.layer.transform=CATransform3DRotate(transform3D, tempVAngle, cos(tempHAngle), 0, sin(tempHAngle));        //image5(上)    //image5与六面体中心的角度为(0,-PI/2)(hAngel为点与水平位置的角度,vAngle为点与竖直位置的角度tempHAngle=_hAngle;tempVAngle=_vAngle-(M_PI/2);transform3D = CATransform3DIdentity;    transform3D.m34 = 1 / -_zoomFactor;transform3D=CATransform3DTranslate(transform3D,   0,   -_referenceSide*sin(-tempVAngle),   -(_referenceSide*cos(-tempVAngle)-_zoomFactor)   );transform3D=CATransform3DRotate(transform3D, tempVAngle, 1,0,0);    if (_imageOver5.image != nil) _imageOver5.layer.transform=CATransform3DRotate(transform3D, tempHAngle, 0, 0, 1);_image5.layer.transform=CATransform3DRotate(transform3D, tempHAngle, 0, 0, 1);            //image6(下)    //image6与六面体中心的角度为(0,PI/2)(hAngel为点与水平位置的角度,vAngle为点与竖直位置的角度    tempHAngle=_hAngle;tempVAngle=_vAngle+(M_PI/2);transform3D = CATransform3DIdentity;    transform3D.m34 = 1 / -_zoomFactor;transform3D=CATransform3DTranslate(transform3D,   0,   -_referenceSide*sin(-tempVAngle),   -(_referenceSide*cos(-tempVAngle)-_zoomFactor)   );transform3D=CATransform3DRotate(transform3D, tempVAngle, 1,0,0);    if (_imageOver6.image != nil) _imageOver6.layer.transform=CATransform3DRotate(transform3D, -tempHAngle, 0, 0, 1);_image6.layer.transform=CATransform3DRotate(transform3D, -tempHAngle, 0, 0, 1);

这样就能够通过透视动画搭建一个正方体了(里面基本都是用的三角函数的知识)

下一步是怎么实现物体能够随手势进行平移

#pragma mark GestureRecognizers//平移手势- (void)didPan:(UIPanGestureRecognizer *)gestureRecognizer {    if (gestureRecognizer.state==UIGestureRecognizerStateBegan) {        if (_delegate && _delegateBeginPan) {            [_delegate panoViewWillBeginPanning:self];        }}if (gestureRecognizer.state==UIGestureRecognizerStateBegan ||gestureRecognizer.state==UIGestureRecognizerStateChanged) {CGPoint translation=[gestureRecognizer translationInView:self];CGFloat newHAngle = self.hAngle-(translation.x/(_zoomFactor/1.5));CGFloat newVAngle = self.vAngle+(translation.y/(_zoomFactor/1.5));if (newHAngle>0 && _rightLimit!=0) {if (newHAngle>_rightLimit) {newHAngle=_rightLimit;}}else if (newHAngle<0 && _leftLimit!=0) {// negative angle to the left, but limit is always positive (absolute value)if (newHAngle<(-_leftLimit)) {newHAngle=-_leftLimit;}}if (newVAngle>0 && _upLimit!=0) {if (newVAngle>_upLimit) {newVAngle=_upLimit;}}else if (newVAngle<0 && _downLimit!=0) {// negative angle to the bottom, but limit is always positive (absolute value)if (newVAngle<(-_downLimit)) {newVAngle=-_downLimit;}}_hAngle=newHAngle;_vAngle=newVAngle;[self render];[gestureRecognizer setTranslation:CGPointZero inView:self];        if (_delegate && _delegateDidPan) {            [_delegate panoViewDidPan:self];        }}    if (gestureRecognizer.state==UIGestureRecognizerStateEnded) {        if (_delegate && _delegateEndPan) {            [_delegate panoViewDidEndPanning:self];        }}}

至于捏合,放大手势就自己写吧,如果想要完整的代码,我近期会上传到github上面的。

这个透视原理不难,最恶心的还是三角函数的计算。。。



0 0
原创粉丝点击