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