iOS極簡模式實(shí)現(xiàn)Webview網(wǎng)頁圖片原生預(yù)覽

溫暖.jpg

前言

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

實(shí)現(xiàn)效果

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

實(shí)現(xiàn)原理

  • HTML加載完成之后注入圖片點(diǎn)擊的JS。
  • 截取JS的點(diǎn)擊事件并拆分出所有圖片URL和當(dāng)前點(diǎn)擊圖片URL。
  • 通過OPTION配置項(xiàng)、配置相關(guān)業(yè)務(wù)參數(shù)。
  • 自動解析懶加載類型HTML網(wǎng)頁、允許用戶自定義懶加載核心屬性。
注入圖片點(diǎn)擊JS需要完成的功能
  • 點(diǎn)擊圖片能夠響應(yīng)圖片的點(diǎn)擊事件。
  • 能夠獲取當(dāng)前點(diǎn)擊圖片的URL。
  • 能夠獲取當(dāng)前HTML中的所有圖片URL。
  • 能夠?qū)D片點(diǎn)擊事件與網(wǎng)頁自帶點(diǎn)擊事件區(qū)分開來。
  • 能夠?qū)?dāng)前點(diǎn)擊圖片URL與所有圖片URL區(qū)分開來。
截取JS的點(diǎn)擊事件解析URL
  • 根據(jù)標(biāo)識符判斷點(diǎn)擊是否執(zhí)行圖片預(yù)覽功能
  • 根據(jù)分隔符拆分當(dāng)前點(diǎn)擊圖片URL與所有圖片URL。
  • 根據(jù)分隔符將所有圖片URL合并成圖片數(shù)組。
  • 具體業(yè)務(wù)過濾不合法圖片URL(eg:包含logo等)。
核心JS代碼實(shí)現(xiàn)
// 通知 iPhone UIWebView 加載 url 對應(yīng)的資源
//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);
    // 發(fā)起請求后這個 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];
        //當(dāng)前實(shí)際點(diǎn)擊圖片的地址
        NSString *indexImageURL = [mixURLArray lastObject];
    }

實(shí)際項(xiàng)目中遇到的問題

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

為了避免重復(fù)調(diào)用,快速實(shí)現(xiàn)功能。對上述功能做了簡單的封裝。

  • UIWebView實(shí)現(xiàn)以下兩行代碼即可
-(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實(shí)現(xiàn)以下兩行代碼
-(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];
  • 僅加載標(biāo)準(zhǔn)正文content中的所有圖片(例如簡書中正文文章中所有圖片),增加了過濾條件OPTION_StandardCoreJS。
self.htmlSDK = [ZWHTMLSDK zw_loadStandardBridgeJSWebview:webView];
  • 如果以上還是不能滿足需求,需要過濾更多的HTML圖片信息,則需要自定義option過濾器。eg:僅加載正文HTML圖片、過濾掉所有圖片URL包含有l(wèi)ogo、avaters的圖片。
ZWHTMLOption *option = [[ZWHTMLOption alloc] init];
  option.getAllImageCoreJS = OPTION_StandardCoreJS;
  option.filterURL = @[@"logo",@"avaters"];
  self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView withOption:option];
  • 需要加載執(zhí)行自定義的JS
ZWHTMLOption *option = [[ZWHTMLOption alloc] init];
  option.zwPreviewJS = @"自定義的JS";
  self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView withOption:option];

圖片預(yù)覽顯示

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

如何使用SDK

強(qiáng)烈建議您使用pod導(dǎo)入,節(jié)省導(dǎo)入依賴的時(shí)間。

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

依賴ZWPhotoPreview圖片顯示框架。

#import "ZWHTMLSDK.h"

關(guān)于圖片保存權(quán)限

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

源碼

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

v0.0.2版本更新記錄

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

  • 【修改】: 重新構(gòu)造圖片預(yù)覽功能、更新圖片預(yù)覽框架ZWPhotoPreview最新版本。

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

v0.0.1版本更新記錄

  • 【新增】: 提供簡便的HTML圖片放大預(yù)覽功能。
  • 【新增】: 提供簡便的HTML圖片過濾功能、用戶自定義過濾參數(shù)。
  • 【新增】: cocoapods支持。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容