前言
初做全景項目鸽捻,涉及到了360度全景展示(也可以是720度的旋轉(zhuǎn))呼巴,查找了很多資料泽腮,很多都是用PanoramaGL這個庫實現(xiàn)的,本人也踩了一下坑衣赶,下面我簡單的總結(jié)一下诊赊。
初識PanoramaGL
此處先提供一個可以在Xcode8運行的 Demo (包含PanoramaGL庫)。你下載下來看一下府瞄,運行碧磅,沒有太大問題,只是第一張圖加載不出遵馆。
從Demo可以看出鲸郊,使用PanoramaGL進行全景圖展示很簡單:
// 在ViewController.m
// #import "PLView.h"
-(void)viewDidLoad
{
[super viewDidLoad];
// 創(chuàng)建全景展示View,設(shè)置代理
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. 創(chuàng)建全景圖 (單張)
NSObject<PLIPanorama> *panorama = nil;
panorama = [PLSphericalPanorama panorama];
[(PLSphericalPanorama *)panorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:[[NSBundle mainBundle] pathForResource:@"pano_sphere" ofType:@"jpg"]]]];
/* 2. 創(chuàng)建全景圖(多張圖片拼接)
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;
*/
// 設(shè)置一個熱點
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 據(jù)說能支持4096x2048 的圖片秆撮,試了一下貌似不行。進去看了一下源碼换况,所謂支持职辨,就是基于2048x1024再縮放,然后進圖片分割排布戈二,效果不行舒裤。所以,自己生成預(yù)覽圖的時候挽拂,需將圖片大小轉(zhuǎn)為2048x1024惭每。
給自己的項目配置PanoramaGL
看著Demo運行的挺好的,但當你把PanoramaGL拖進你的項目亏栈,編譯台腥,一大堆錯誤!原因是Demo把不能運行的坑都踩了绒北,這個PanoramaGL庫2011年開始就不再維護了黎侈。庫是在MRC環(huán)境寫的,因此闷游,直接在現(xiàn)在Xcode 的ARC環(huán)境編譯會出錯峻汉。
解決以上問題:
在用MRC 環(huán)境寫的文件 添加 -fno-objc-arc,
屬于PanoramaGL基本這個庫的文件基本都要添加脐往,但是休吠,不是全部! 注意业簿,文件后綴.c的文件不用添加 -fno-objc-arc
好不容易將這么多文件添加了-fno-objc-arc 瘤礁,再編譯一下,蒙蔽了梅尤,瞬間幾十個錯誤:
解決上面這個問題柜思,有三個解決方案:
解決方案一:
選擇所有導(dǎo)入的.c文件岩调,將屬性的 identity and type 改為Objective-C Source。
解決方案二:
選擇所有導(dǎo)入的.c文件赡盘,將.c修改為.m
解決方案三:
將Compile Sources As 改為 Objective-C++号枕。
方案三由于修改所有文件的編譯類型,所有可能會導(dǎo)致其他包括c陨享、c++代碼的提示錯誤葱淳,不過都是些的提示異常,按提示修改即可霉咨。
改完了蛙紫,編譯,終于通過途戒。
項目使用實例
先給大家貼一下使用PanoramaGL實現(xiàn)預(yù)覽全景圖的控制器代碼吧:
// 此處是push出來的預(yù)覽全景圖控制器
// CPPreviewPanoController.h
@interface CPPreviewPanoController : UIViewController
@property (strong, nonatomic) UIImage *previewImage;
@end
// Created by JasonSu on 2017/5/17.
// Copyright ? 2017年 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];
// 創(chuàng)建預(yù)覽
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 里面的對象默認為PHAsset
NSLog(@"%@", 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設(shè)置 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];
}
// 點擊預(yù)覽
- (void)didPreviewImageView:(CPImagePreview *)imgView
{
// CPLog(@"控制器點擊預(yù)覽");
CPPreviewPanoController *previewVc = [[CPPreviewPanoController alloc]init];
previewVc.previewImage = imgView.image;
[self.navigationController pushViewController:previewVc animated:YES];
}
最后
好了喷斋,此次分享利用PanoramaGL生成360度全景預(yù)覽圖 就到這里,已是凌晨蒜茴,希望可以幫到你星爪。有問題的小伙伴可以留言,大家一起交流粉私。