iOS全景效果實現

WenBo丨星空灬發表於2018-01-04

前言

在我做一個商城類App的時候,遇到一個需求,就是需要把安裝師傅的專案效果圖360°全景展示出來,以前也從來沒有接觸過,一開始也並沒有具體的實現思路,後來同事給我推薦了一個基於OpenGL支援球,立方體,圓柱的庫,這是一個很老的庫了,但是效果卻還不錯,最後工程也整合和使用了這個庫,順便也介紹幾種其他的實現方式,以便以後做專案查閱。

一、PanoramaGL

上面這個庫的連結是GitHub上一個大神skyfox維護的,他在原有基礎之上對一些問題進行了修復,這個庫沒有使用ARC,整合的時候相對麻煩一點,因為庫的作者沒有對庫進行維護,在有些效果上,效能開銷還是挺大的,下面開始介紹整合與使用吧。

  • 整合,將PanoramaGL資料夾拖入工程,並在Build Phases Compile Source庫檔案.m中新增-fno-objc-arc(注意:每個庫檔案.m都要新增,不然執行會報錯),如下圖所示:
    螢幕快照 2018-01-03 下午12.05.42.png
    螢幕快照 2018-01-03 下午12.08.58.png
  • 具體使用:PanoramaGL的demo主要提供了六種效果展示,有六張圖片拼接,也有直接使用一張全景圖片,我專案裡使用的是Sphere這種效果,圖片支援大小是2048x1024。在構建PLImage的時候,我不得不吐槽下自己,因為demo都是通過圖片路徑得到PLImage,於是我就想到用AFN封裝一個圖片下載方法,下載圖片後,獲取圖片儲存在本地路徑,來構建PLImage。之後SDWebImage瞭解和使用的比較多,發現SDWebImage可以直接下載圖片並快取,好了,不多說了,直接上程式碼吧。
- (void)setupPLView {
    //JSON loader example (see json.data, json_s2.data and json_cubic.data)
    //[plView load:[PLJSONLoader loaderWithPath:[[NSBundle mainBundle] pathForResource:@"json_cubic" ofType:@"data"]]];
    /**  < 設定代理 >  */
    plView.delegate = self;
    /**  < 設定靈敏度 >  */
    /**  <
     #define kDefaultAccelerometerSensitivity    7.0f
     #define kDefaultAccelerometerInterval        1.0f/60.0f
     #define kAccelerometerSensitivityMinValue    1.0f
     #define kAccelerometerSensitivityMaxValue    10.0f
     #define kAccelerometerMultiplyFactor        100.0f
     >  */
//    plView.accelerometerSensitivity = 10;
//
//    /**  < 加速更新頻率 >  */
//    plView.accelerometerInterval = 1 / 45.0;
//    /**  < 加速度 >  */
//    plView.isAccelerometerEnabled = NO;
//    /**  < X軸加速度 >  */
//    plView.isAccelerometerLeftRightEnabled = NO;
//    /**  < Y軸加速度 >  */
//    plView.isAccelerometerUpDownEnabled = NO;
//    /**  < 慣性 >  */
//    plView.isInertiaEnabled = NO;
//    /**  < 三指恢復初始化 >  */
//    plView.isResetEnabled = NO;
    
    /**  < 載入本地 >  */
    [self selectPanorama:0];
    
    /**  < 載入網路全景圖 >  */
//    [self loadData];
}
複製程式碼
- (void)loadData {
    NSObject<PLIPanorama> *panorama = [PLSphericalPanorama panorama];
    [[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514970914547&di=2eb3de621ad48c0f9961e99e3176ad65&imgtype=0&src=http%3A%2F%2Fbpic.ooopic.com%2F16%2F00%2F89%2F16008943-6247a25ba16e2cd1e23842d461d60fa5.jpg"] options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
        
    } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
        NSLog(@"%@",imageURL);
        /**  < 1、第一種載入方式 >  */
//        [(PLSphericalPanorama *)panorama setTexture:[PLTexture textureWithImage:[PLImage imageWithBuffer:data]]];
        /**  < 2、第二種載入方式 >  */
        /**  < 是否快取在磁碟 >  */
        [[SDWebImageManager sharedManager] diskImageExistsForURL:imageURL completion:^(BOOL isInCache) {
            if (isInCache) {
                /**  < 獲取快取key >  */
                NSString *cacheImageKey = [[SDWebImageManager sharedManager]  cacheKeyForURL:imageURL];
                /**  < 獲取快取路徑 >  */
                NSString *cacheImagePath = [[SDImageCache sharedImageCache] defaultCachePathForKey:cacheImageKey];
                 [(PLSphericalPanorama *)panorama setTexture:[PLTexture textureWithImage:[PLImage imageWithPath:cacheImagePath]]];
            }
        }];
        
        //Add a hotspot
        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];
        dispatch_async(dispatch_get_main_queue(), ^{
            [plView setPanorama:panorama];
            /**  < 設定角度 >  */
            PLRotation ro = PLRotationMake(40.0, 0.0, 0.0);
            [plView.camera resetCurrentC:ro Pitch:ro.pitch yaw:ro.yaw];
        });
    }];
}
複製程式碼

到這裡全景圖效果都已經實現了,在專案中運用的也只有這麼多,如果還有更多需求,可以檢視相關標頭檔案提供的方法吧。具體詳情請看GitHub:PanoramaGLDemo,下面也帖出執行效果圖吧:

Untitled.gif

問題解決

1、解決點選 PLHotspot 不響應 didClickHotspot 代理方法的問題

二、JAPanoView

JAPanoView是一個UIView子類,從立方全景影象建立顯示360 - 180度全景,互動式平移和縮放。可以新增任何UIView JAPanoView熱點。具體使用檢視GitHub說明。

三、Panorama

360°球形全景檢視,基於OpenGL實現,具體使用檢視GitHub上的Demo。

四、three.js

JavaScript 3D library。

五、自己實現

GLKit.framework 與OpenGLES實現,這個需要對OpenGL比較精通才能實現吧。

結語

全景圖在一般的專案中也用不到,自己寫篇文章做下記錄,這篇文章主要對我在專案中實現全景圖程式碼做了記錄,其他方法只是為了擴充和了解,希望能對你能有所幫助。

參考文章

1、iOS全景
2、PanoramaGL在IOS的使用
3、iOS PanoramaGL(全景展示)用法

相關文章