iOS極簡模式實現Webview網頁圖片原生預覽

溫暖.jpg

前言

最近的幾個項目中都需要加載大量的HTML,需要將HTML中的圖片在點擊時實現原生預覽。由于HTML的來源很復雜,包括有后臺框架編輯的、第三方提供的、網絡抓取的等等。所以只能采取獲取HTML之后前端注入JS事件來觸發圖片點擊事件,獲取當前頁面的所有圖片地址。由于實現的原理很簡單(兩行代碼),就不需要使用JavaScriptCore或者其他第三方框架了。

實現效果

HTMLImage.gif
框架整體介紹
  • 該框架為一個通用HTML圖片預覽框架,旨在提供一種簡單快捷的調用方式來native預覽網頁圖片。
  • 同時支持UIWebView與WKWebView。
  • 支持網頁圖片自定義過濾規則。過濾“頭像、廣告”之類的小圖標。
  • 支持用戶自定義核心抓取圖片JS、自定義解析規則。
  • 支持配置參數確定是否僅抓取正文(conent)部分圖片。
  • SDK支持解析懶加載類型HTML網頁(ps:簡書更新以后圖片加載就是采用的滾動加載模式)

實現原理

  • HTML加載完成之后注入圖片點擊的JS。
  • 截取JS的點擊事件并拆分出所有圖片URL和當前點擊圖片URL。
  • 通過OPTION配置項、配置相關業務參數。
  • 自動解析懶加載類型HTML網頁、允許用戶自定義懶加載核心屬性。
注入圖片點擊JS需要完成的功能
  • 點擊圖片能夠響應圖片的點擊事件。
  • 能夠獲取當前點擊圖片的URL。
  • 能夠獲取當前HTML中的所有圖片URL。
  • 能夠將圖片點擊事件與網頁自帶點擊事件區分開來。
  • 能夠將當前點擊圖片URL與所有圖片URL區分開來。
截取JS的點擊事件解析URL
  • 根據標識符判斷點擊是否執行圖片預覽功能
  • 根據分隔符拆分當前點擊圖片URL與所有圖片URL。
  • 根據分隔符將所有圖片URL合并成圖片數組。
  • 具體業務過濾不合法圖片URL(eg:包含logo等)。
核心JS代碼實現
// 通知 iPhone UIWebView 加載 url 對應的資源
//PhoneGap處理方式
function loadURL(url) {
    var iFrame;
    iFrame = document.createElement("iframe");
    iFrame.setAttribute("src", url);
    iFrame.setAttribute("style", "display:none;");
    iFrame.setAttribute("height", "0px");
    iFrame.setAttribute("width", "0px");
    iFrame.setAttribute("frameborder", "0");
    document.body.appendChild(iFrame);
    // 發起請求后這個 iFrame 就沒用了,所以把它從 dom 上移除掉
    iFrame.parentNode.removeChild(iFrame);
    iFrame = null;
}
function zwPreviewImageClickAction(){
    var imgs=document.getElementsByTagName('img');
    var length=imgs.length;
    var allSrc='';
    for(var i=0;i<length;i++){
        var img=imgs[i];
        var imaSrc = '';
        if (img.src.length){
            imaSrc = img.src;
        }else{
            imaSrc = img.getAttribute('data-original-src');
        }
        if (allSrc.length) {
            allSrc = allSrc+'^^^'+imaSrc;
        }else{
            allSrc = imaSrc;
        }
    }
    for(var i=0;i<length;i++){
        var img=imgs[i];
        img.onclick=function(){
//            window.location.href='zw-image-preview:'+allSrc + '###'+this.src;
            loadURL("zw-image-preview:"+allSrc+ '###'+this.src);
        }
    }
}
zwPreviewImageClickAction();
截取JS事件并解析URL
  1. UIWebView在shouldStartLoadWithRequest代理方法中
  2. WKWebView在decidePolicyForNavigationAction代理方法中
if ([request.URL.scheme isEqualToString:@"zw-image-preview"]) {
        NSString *urlPath = [request.URL.absoluteString substringFromIndex:[@"zw-image-preview:" length]];
        NSArray *mixURLArray = [urlPath componentsSeparatedByString:@"###"];
        //圖片地址合集
        NSString *allImageURL = [mixURLArray firstObject];
        //當前實際點擊圖片的地址
        NSString *indexImageURL = [mixURLArray lastObject];
    }

實際項目中遇到的問題

  • HTML來源與展示界面比較復雜,無法統一WebView界面。導致以上代碼需要重復調用多次。
  • HTML的格式比較奇葩,鬼知道后臺使用的什么轉換器。
  • 圖片地址命名會出現與分隔符沖突等等。
  • HTML中混雜了小圖標(logo、頭像等)需要過濾。
封裝JS與URL解析

為了避免重復調用,快速實現功能。對上述功能做了簡單的封裝。

  • UIWebView實現以下兩行代碼即可
-(void)webViewDidFinishLoad:(UIWebView *)webView{
    self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if ([self.htmlSDK zw_handlePreviewImageRequest:request]) {
        return NO;
    }
    return YES;
}
  • WKWebView實現以下兩行代碼
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView];
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    decisionHandler(WKNavigationActionPolicyAllow);
    [self.htmlSDK zw_handlePreviewImageRequest:navigationAction.request];
}
效果展示
normalPreview.gif
SDK源碼解析
  • 加載HTML中的所有圖片,包括推廣廣告圖、logo、用戶評論頭像等等。參照上圖:包括了簡書的logo、下文的推廣鏈接圖。
self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView];
  • 僅加載標準正文content中的所有圖片(例如簡書中正文文章中所有圖片),增加了過濾條件OPTION_StandardCoreJS。
self.htmlSDK = [ZWHTMLSDK zw_loadStandardBridgeJSWebview:webView];
  • 如果以上還是不能滿足需求,需要過濾更多的HTML圖片信息,則需要自定義option過濾器。eg:僅加載正文HTML圖片、過濾掉所有圖片URL包含有logo、avaters的圖片。
ZWHTMLOption *option = [[ZWHTMLOption alloc] init];
  option.getAllImageCoreJS = OPTION_StandardCoreJS;
  option.filterURL = @[@"logo",@"avaters"];
  self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView withOption:option];
  • 需要加載執行自定義的JS
ZWHTMLOption *option = [[ZWHTMLOption alloc] init];
  option.zwPreviewJS = @"自定義的JS";
  self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView withOption:option];

圖片預覽顯示

  • 按照上面兩行代碼實現調用即可預覽顯示。SDK內部已經封裝了圖示的顯示模式。
//預覽視圖、已集成SDK中
ZWPreviewImageView *showView = [ZWPreviewImageView showImageWithArray:allImageArray withShowIndex:index];
[showView showRootWindow];
  • 如果用戶需要自定義(嫌棄>_<)圖片瀏覽器,只需要實現調用以下的block。allImageArray:過濾后所有URL數組。index:當前操作圖片的序號。
self.htmlSDK.blockHandlePreview = ^(NSArray *allImageArray, NSInteger index) {
        //自定義圖片預覽
    };

如何使用SDK

強烈建議您使用pod導入,節省導入依賴的時間。

  • 使用cocoaPods導入(搜索不到請更新本地倉庫)
pod 'ZWHTMLImage',       '~> 0.0.2'
  • 直接將文件ZWHTMLImage拖入工程中

依賴ZWPhotoPreview圖片顯示框架。

#import "ZWHTMLSDK.h"

關于圖片保存權限

  • 長按保存功能需要用戶info.plist中配置權限
Privacy - Photo Library Additions Usage Description

源碼

源碼放在GitHub上,歡迎指正,記得star哦!

v0.0.2版本更新記錄

  • 【新增】: 支持懶加載類型網頁圖片的讀取功能。

  • 【修改】: 重新構造圖片預覽功能、更新圖片預覽框架ZWPhotoPreview最新版本。

  • 【新增】: 提供圖片快速預覽、手勢拖放動畫、手勢縮放、長按保存、頁碼選擇等最新功能。

v0.0.1版本更新記錄

  • 【新增】: 提供簡便的HTML圖片放大預覽功能。
  • 【新增】: 提供簡便的HTML圖片過濾功能、用戶自定義過濾參數。
  • 【新增】: cocoapods支持。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容