iOS 上有很多瀏覽器都有“看圖模式”這一功能,實現這一功能可能有很多種途徑,最近接觸到了這方面的工作,所以在此把我的思路記錄下來。過程雖然比較簡短,但日後可能會用到,如有更好的方案也可以對比下,取長補短。
這次並不會用到什麼新特性(比如 WKWebView
)。而且方案很簡單,分三步:
- 獲取網頁中的圖片(鏈接)
- 將圖片(鏈接)傳給圖片查看器
- 完成點擊圖片的回調及動畫
這裏不可避免的會要用到 Javascript 來獲取 <img>
元素內容,添加點擊事件等。第一步很簡單,幾行 js 代碼搞定:
1 2 3 4 5 6 7 8 9
|
function getAllImageUrl(){ var imgs = document.getElementsByTagName("img"); var urlArray = []; for (var i=0;i<imgs.length;i++){ var src = imgs[i].src; urlArray.push(src); } return urlArray.toString(); }
|
第二步也不難,因爲圖片查看器可以用現成的第三方庫,比如 IDMPhotoBrowser
,只需要傳入一個 NSURL
數組就行。
第三步需要繞個彎子。
首先是用 js 給圖片添加點擊事件,這個簡單:
1 2 3 4 5 6
|
function setImage(){ var imgs = document.getElementsByTagName("img"); for (var i=0;i<imgs.length;i++){ imgs[i].setAttribute("onClick","imageClick("+i+")"); } }
|
然後是動畫,還好 IDMPhotoBrowser
提供了一個動畫的接口:
1
|
- (id)initWithPhotos:(NSArray *)photosArray animatedFromView:(UIView*)view
|
這裏需要傳入一個 view
來作爲動畫的起始參數。我的做法是在 webView
上添加一個佔位視圖,並正好覆蓋在被點擊圖片之上,將其作爲動畫的起始參數。這就需要從網頁上獲取被點擊圖片的 frame
,還有圖片的內容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
function getImageRect(i){ var imgs = document.getElementsByTagName("img"); var rect; rect = imgs[i].getBoundingClientRect().left+"::"; rect = rect+imgs[i].getBoundingClientRect().top+"::"; rect = rect+imgs[i].width+"::"; rect = rect+imgs[i].height; return rect; } function getImageData(i){ var imgs = document.getElementsByTagName("img"); var img=imgs[i]; var canvas=document.createElement("canvas"); var context=canvas.getContext("2d"); canvas.width=img.width; canvas.height=img.height; context.drawImage(img,0,0,img.width,img.height); return canvas.toDataURL("image/png") }
|
在獲取圖片內容時我並沒有通過圖片的 url 在 OC 代碼中重新下載一次圖片,而是選擇將 web 中已經下載好的圖片轉成 png 格式傳給 OC。但 stringByEvaluatingJavaScriptFromString:
方法返回的都是字符串,而且 js 返回的數據編碼還是 base64 格式的。這裏用到 skpsmtpmessage
這個第三方庫將其解碼爲 NSData
:
1 2 3 4 5 6
|
NSString *javascript = [NSString stringWithFormat: NSString *stringData = [webView stringByEvaluatingJavaScriptFromString:javascript]; stringData = [stringData substringFromIndex:22]; // strip the string "data:image/png:base64," NSData *data = [NSData decodeWebSafeBase64ForString:stringData]; UIImage *image = [UIImage imageWithData:data]
|
嗯,最後完成圖片點擊事件的函數,在其中獲取被點擊圖片的 frame,並拼湊成以 “clickgirl” 開頭的 url
,當然如果你喜歡用 “sexualgirl” 之類的也可以:
1 2 3 4 5
|
function imageClick(i){ var rect = getImageRect(i); var url="clickgirl::"+i+"::"+rect; document.location = url; }
|
上面的 url
在 UIWebViewDelegate
的 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
中會獲取到,我貼上完整代碼,順便去掉下討厭的百度推廣。不要忘了在 browser
出現後將佔位圖片移除:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *requestString = [[request URL] absoluteString]; if ([requestString hasPrefix:@"http://pos.baidu.com"]) { return NO; } NSArray *components = [requestString componentsSeparatedByString:@"::"]; if ([components[0] isEqualToString:@"clickgirl"]) { int imgIndex = [components[1] intValue]; CGRect frame = CGRectMake([components[2] floatValue], [components[3] floatValue], [components[4] floatValue], [components[5] floatValue]); UIImageView *showView = [[UIImageView alloc] initWithFrame:frame]; NSString *javascript = [NSString stringWithFormat: @"getImageData(%d);", imgIndex]; NSString *stringData = [webView stringByEvaluatingJavaScriptFromString:javascript]; stringData = [stringData substringFromIndex:22]; NSData *data = [NSData decodeWebSafeBase64ForString:stringData]; UIImage *image = [UIImage imageWithData:data]; showView.image = image; [_webView addSubview:showView]; NSString *urls = [_webView stringByEvaluatingJavaScriptFromString:@"getAllImageUrl();"]; IDMPhotoBrowser *browser = [[IDMPhotoBrowser alloc] initWithPhotos:[IDMPhoto photosWithURLs:[urls componentsSeparatedByString:@","]] animatedFromView:showView]; [browser setInitialPageIndex:imgIndex]; browser.useWhiteBackgroundColor = YES; [self presentViewController:browser animated:YES completion:nil]; [showView removeFromSuperview]; } return YES; }
|
其實有些網站只是在手機站上加了百度推廣之類的,而在 PC 端可能並沒有。至於符合查看手機上 web 的佈局,可以在調試時打開 Mac 上的 Safari,點擊“開發”菜單(我相信你肯定早已開啓開發模式),選擇你調試的那臺設備,然後會看到你正在調試的程序和 webview
當前打開的域名。點擊後可以展開 Web 檢查器,使用方法跟 Mac 上 Safari 的 Web 檢查器一樣:
Web
檢查器
這樣就可以查看手機上的 Web 元素,方便我們 js 代碼的編寫。
其實在做公司項目時看了下 IDMPhotoBrowser
的代碼,並做了一點兒優化和定製,尤其是在動畫方面,這個控件還有很多流程和性能優化的空間。
最後放上 Demo 的 Github:https://github.com/yulingtianxia/WebViewImageClick