当前位置: 代码迷 >> 综合 >> 在iOS利用动画实现全景视图
  详细解决方案

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

热度:35   发布时间:2023-10-31 05:04:30.0

干货,干货,这个绝对是干货,研究了很久,参考了网上的代码,终于明白了如何利用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上面的。

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



  相关解决方案