前言
初做全景项目,涉及到了360度全景展示(也可以是720度的旋转),查找了很多资料,很多都是用PanoramaGL这个库实现的,本人也踩了一下坑,下面我简单的总结一下。
初识PanoramaGL
此处先提供一个可以在Xcode8运行的 Demo (包含PanoramaGL库)。你下载下来看一下,运行,没有太大问题,只是第一张图加载不出。
从Demo可以看出,使用PanoramaGL进行全景图展示很简单:
// 在ViewController.m // #import "PLView.h"-(void)viewDidLoad{[super viewDidLoad];// 创建全景展示View,设置代理self.plView.delegate = self;//JSON loader example (see json.data, json_s2.data and json_cubic.data)//[plView load:[PLJSONLoader loaderWithPath:[[NSBundle mainBundle] pathForResource:@"json_cubic" ofType:@"data"]]];// 1. 创建全景图 (单张)NSObject<PLIPanorama> *panorama = nil;panorama = [PLSphericalPanorama panorama];[(PLSphericalPanorama *)panorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_sphere" ofType:@"jpg"]]]];/* 2. 创建全景图(多张图片拼接)PLCubicPanorama *cubicPanorama = [PLCubicPanorama panorama];[cubicPanorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_f" ofType:@"jpg"]]] face:PLCubeFaceOrientationFront];[cubicPanorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_b" ofType:@"jpg"]]] face:PLCubeFaceOrientationBack];[cubicPanorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_l" ofType:@"jpg"]]] face:PLCubeFaceOrientationLeft];[cubicPanorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_r" ofType:@"jpg"]]] face:PLCubeFaceOrientationRight];[cubicPanorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_u" ofType:@"jpg"]]] face:PLCubeFaceOrientationUp];[cubicPanorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_d" ofType:@"jpg"]]] face:PLCubeFaceOrientationDown];panorama = cubicPanorama;*/// 设置一个热点PLTexture *hotspotTexture = [PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"hotspot" ofType:@"png"]]];PLHotspot *hotspot = [PLHotspot hotspotWithId:(kIdMin + random() % ((kIdMax + 1) - kIdMin)) texture:hotspotTexture atv:0.0f ath:0.0f width:0.08f height:0.08f];[panorama addHotspot:hotspot];// 将全景图展示[self.plView setPanorama:panorama];}复制代码
此处给大家说一下,这里单张的全景图片的<宽高比限定为2:1>
而PanoramaGL仅支持单张分辨率2048x1024的全景图,里面的 PLSpherical2Panorama 据说能支持4096x2048 的图片,试了一下貌似不行。进去看了一下源码,所谓支持,就是基于2048x1024再缩放,然后进图片分割排布,效果不行。所以,自己生成预览图的时候,需将图片大小转为2048x1024。
给自己的项目配置PanoramaGL
看着Demo运行的挺好的,但当你把PanoramaGL拖进你的项目,编译,一大堆错误!原因是Demo把不能运行的坑都踩了,这个PanoramaGL库开始就不再维护了。库是在MRC环境写的,因此,直接在现在Xcode 的ARC环境编译会出错。
解决以上问题:
在用MRC 环境写的文件 添加 -fno-objc-arc, 属于PanoramaGL基本这个库的文件基本都要添加,但是,不是全部! 注意,文件后缀.c的文件不用添加 -fno-objc-arc
好不容易将这么多文件添加了-fno-objc-arc ,再编译一下,蒙蔽了,瞬间几十个错误:
解决上面这个问题,有三个解决方案:
解决方案一:
选择所有导入的.c文件,将属性的 identity and type 改为Objective-C Source。
解决方案二:
选择所有导入的.c文件,将.c修改为.m
解决方案三:
将Compile Sources As 改为 Objective-C++。 方案三由于修改所有文件的编译类型,所有可能会导致其他包括c、c++代码的提示错误,不过都是些的提示异常,按提示修改即可。
改完了,编译,终于通过。
项目使用实例
先给大家贴一下使用PanoramaGL实现预览全景图的控制器代码吧:
// 此处是push出来的预览全景图控制器// CPPreviewPanoController.h@interface CPPreviewPanoController : UIViewController@property (strong, nonatomic) UIImage *previewImage;@end复制代码
// Created by JasonSu on /5/17.// Copyright © JasonSu. All rights reserved.//// CPPreviewPanoController.m#import "CPPreviewPanoController.h"#import "PLView.h"#define kPreviewSize CGSizeMake(2048, 1024)@interface CPPreviewPanoController ()<PLViewDelegate>@property (strong , nonatomic) PLView *plView;@end@implementation CPPreviewPanoController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor whiteColor];// 创建预览self.plView = [[PLView alloc]initWithFrame:CGRectMake(0, 64, CPSCREEN_WIDTH, CPSCREEN_HEIGHT-64)];self.plView.delegate = self;[self.view addSubview:self.plView];if (!self.previewImage) {return;}UIImage *previewImg = [self reSizeImage:self.previewImage toSize:kPreviewSize];NSLog(@"改变尺寸后的image==%@", previewImg);CGImageRef cgRef = previewImg.CGImage;NSObject<PLIPanorama> *panorama = nil;// (supports up 2048x1024 texture) panorama = [PLSphericalPanorama panorama];[(PLSphericalPanorama *)panorama setTexture:[PLTexture textureWithImage:[PLImage imageWithCGImage:cgRef]]];[self.plView setPanorama:panorama];}- (void)viewDidDisappear:(BOOL)animated{[super viewDidDisappear:YES];[self.plView removeFromSuperview];self.plView.delegate = nil;self.plView = nil;}-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{return YES;}/// 修改图片尺寸- (UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize{UIGraphicsBeginImageContext(CGSizeMake(reSize.width, reSize.height));[image drawInRect:CGRectMake(0, 0, reSize.width, reSize.height)];UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();return reSizeImage;}复制代码
本项目选择图片使用QBImagePicker
下面展示上一级控制器.m (即选择手机相册图片的控制器)的部分代码
#import "QBImagePickerController.h"// 遵守QBImagePickerControllerDelegate/// 选择图片- (void)addPhoto:(CPImageUpButton *)btn{// CPLog(@"添加图片");QBImagePickerController *imagePickerController = [QBImagePickerController new];imagePickerController.delegate = self;imagePickerController.allowsMultipleSelection = NO; // 单选// 只获取图片资源imagePickerController.mediaType = QBImagePickerMediaTypeImage;[self presentViewController:imagePickerController animated:YES completion:nil];}#pragma mark - QBImagePickerController delegate 图片选择代理- (void)qb_imagePickerController:(QBImagePickerController *)imagePickerController didFinishPickingAssets:(NSArray *)assets {// iOS8 以后,assets 里面的对象默认为PHAssetNSLog(@"%@", assets);// 此处默认单选PHAsset *set = assets.firstObject;// 通过图片宽高判,这个是我项目的主要判断if ( set.pixelWidth/set.pixelHeight !=2) {[MBProgressHUD showError:@"您选的不是全景图片"];return;}// 类型判断if (!(set.mediaType == 1 && set.mediaSubtypes == 0)) {[MBProgressHUD showError:@"您选的不是全景图片"];return;}// 获取图片(获得UIImage)PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;// 注意:targetSize设置 PHImageManagerMaximumSize 有可能造成卡顿,原来为Screen.size[[PHImageManager defaultManager] requestImageForAsset:set targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {NSLog(@"result==%@ info==%@", result,info);UIImage *photo = result;[self.photosArray addObject:photo];}];[self dismissViewControllerAnimated:YES completion:nil];}// 用户取消选择图片- (void)qb_imagePickerControllerDidCancel:(QBImagePickerController *)imagePickerController {//do something[self dismissViewControllerAnimated:YES completion:nil];}复制代码
// 点击预览- (void)didPreviewImageView:(CPImagePreview *)imgView{// CPLog(@"控制器点击预览");CPPreviewPanoController *previewVc = [[CPPreviewPanoController alloc]init];previewVc.previewImage = imgView.image;[self.navigationController pushViewController:previewVc animated:YES];}复制代码
最后
好了,此次分享利用PanoramaGL生成360度全景预览图 就到这里,已是凌晨,希望可以帮到你。有问题的小伙伴可以留言,大家一起交流。