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

溫暖.jpg

前言

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

實現(xiàn)效果

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

實現(xiàn)原理

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

實際項目中遇到的問題

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

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

  • UIWebView實現(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實現(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ù)覽顯示

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

如何使用SDK

強烈建議您使用pod導(dǎo)入廓块,節(jié)省導(dǎo)入依賴的時間。

  • 使用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)系作者
  • 序言:七十年代末舷礼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子郊闯,更是在濱河造成了極大的恐慌妻献,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虚婿,死亡現(xiàn)場離奇詭異旋奢,居然都是意外死亡,警方通過查閱死者的電腦和手機然痊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屉符,“玉大人剧浸,你說我怎么就攤上這事〈V樱” “怎么了唆香?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吨艇。 經(jīng)常有香客問我躬它,道長,這世上最難降的妖魔是什么东涡? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任冯吓,我火速辦了婚禮倘待,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘组贺。我一直安慰自己凸舵,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布失尖。 她就那樣靜靜地躺著啊奄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掀潮。 梳的紋絲不亂的頭發(fā)上菇夸,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音仪吧,去河邊找鬼庄新。 笑死,一個胖子當(dāng)著我的面吹牛邑商,可吹牛的內(nèi)容都是我干的摄咆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼人断,長吁一口氣:“原來是場噩夢啊……” “哼吭从!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恶迈,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤涩金,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后暇仲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體步做,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年奈附,在試婚紗的時候發(fā)現(xiàn)自己被綠了全度。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡斥滤,死狀恐怖将鸵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情佑颇,我是刑警寧澤顶掉,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站挑胸,受9級特大地震影響痒筒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一簿透、第九天 我趴在偏房一處隱蔽的房頂上張望移袍。 院中可真熱鬧,春花似錦萎战、人聲如沸咐容。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽戳粒。三九已至,卻和暖如春虫啥,著一層夾襖步出監(jiān)牢的瞬間蔚约,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工涂籽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苹祟,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓评雌,卻偏偏與公主長得像树枫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子景东,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容