您好,登錄后才能下訂單哦!
webp格式圖片
webp格式圖片是google推出的,相比jpg png有著巨大的優勢,同樣質量的圖片webp格式的圖片占用空間更小,在像電商這樣圖片比較多的App中,使用webp格式圖片會很有優勢。
引言
很早之前,我們的項目中就已經采用了webp格式,但是由于webView本身并不能解析webp格式,所以我們基于webView的文章詳情頁就無法使用到這項優化。
那么有沒有什么辦法能實現呢?當然是有的。
在開始技術講解之前需要先說明,本文的技術方案,是基于本項目的情況:文章的正文大部分通過接口直接獲取到,通過在客戶端本地進行html正文組裝,最后通過webView的loadHTMLString方法進行加載顯示。普通的圖片可以通過轉換鏈接得到webp服務器獲取到相應的webp版的圖片。
本項目中,圖片緩存使用了SDWebImage,并且開啟了webp支持功能,那么我們對詳情頁webView的處理也會基于此來實現。
通過思考,方案其實還是比較明確的,就是替換html中圖片鏈接,通過客戶端下載webp圖片,然后在通過js刷新出頁面上的下完的圖片,但實際開發中也遇到了一些坑,比如:
最終的技術實現:
1.對下載回來的html內容進行處理,獲取所有圖片鏈接,并進行webp鏈接處理轉換
對html內容的解析處理我使用的是Objective-C-HMTL-Parser,但是該庫已經多年不維護,這里有我fork后進行部分優化調整的版本:https://github.com/YueRuo/Objective-C-HMTL-Parser (本地下載)
處理html圖片核心處理邏輯代碼:
@try { HTMLParser *parser = [[HTMLParser alloc] initWithString:htmlContent error:&error]; HTMLNode *bodyNode = [parser body]; if (error) { return; } //得到所有的img標簽 NSArray *inputNodes = [bodyNode findChildTags:@"img"]; for (HTMLNode *inputNode in inputNodes) { NSString *imageSrc = [inputNode getAttributeNamed:@"src"]; if (!imageSrc) { continue; } NSString *newSrc = [[GlobalVariable shareInstance] resizeWebpImageWithUrl:imageSrc size:CGSizeMake((SCREEN_WIDTH - 20) * 2, 0)];//根據原圖片,得到webp服務器使用的圖片鏈接,需要有webp處理服務器 //檢查本地圖片緩存 NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:[NSURL URLWithString:newSrc]]; NSString *localPath = [[SDImageCache sharedImageCache] defaultCachePathForKey:key]; NSString *webpImage = newSrc; BOOL localExsit = [[NSFileManager defaultManager] fileExistsAtPath:localPath]; if (localExsit) { newSrc = [NSString stringWithFormat:@"file://%@", localPath]; } //存儲疑似webp圖片和原圖片,如果newSrc和webp相同則說明本地沒有緩存圖片 [_webpImageUrlDic setObject:webpImage forKey:newSrc]; if(localExsit){ setAttributeNamed(inputNode->_node, "src", [newSrc cStringUsingEncoding:NSUTF8StringEncoding]); }else{ setAttributeNamed(inputNode->_node, "src", "詳情頁占位圖@2x.png"); } //給img標簽中增加一個叫osrc的屬性,便于后續處理 setAttributeNamed(inputNode->_node, "osrc", [newSrc cStringUsingEncoding:NSUTF8StringEncoding]); } htmlContent = [NSMutableString stringWithString:parser.doc.rawContents]; } @catch (NSException *exception) { } @finally { [webView loadHTMLString:htmlContent baseURL:baseUrl]; }
2.用原生方法下載webp圖片,緩存到本地
下載之后會存儲為jpg或png格式,這樣就可以被webView進行本地加載,但是需要注意gif的存儲特殊處理。
另外通過實驗,直接通過js無法實時更新下載到本地的圖片,只好通過圖片的base64encode數據加載方式實現。
具體代碼如下:
- (void)webViewDidFinishLoad:(UIWebView *)web { //處理webp格式加載 [_webpImageUrlDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if([obj isEqualToString:key]){//說明這圖沒有緩存,還需要下載 [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:obj] options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { if (image&&finished) { NSString *js; NSRange range = [[obj lowercaseString] rangeOfString:@".gif"];//檢查是否是gif BOOL isGif = (range.location != NSNotFound); if (!isGif) { [[SDImageCache sharedImageCache] storeImage:image forKey:obj]; NSString *base64 = [UIImageJPEGRepresentation(image,1) base64EncodedStringWithOptions:0]; js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/jpeg;base64,%@')",key,base64]; }else{//gif的圖片如果直接存儲,會變成jpg從而失去動畫,因此要特殊處理 [[SDImageCache sharedImageCache] storeImage:image recalculateFromImage:false imageData:data forKey:key toDisk:true]; NSString *base64 = [data base64EncodedStringWithOptions:0]; js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/gif;base64,%@')",key,base64]; } [NSThread excuteInMainThread:^{ [webView stringByEvaluatingJavaScriptFromString:js]; } async:false]; } }]; } else {//緩存中存在,那么直接加載吧 NSString *js; NSRange range = [[obj lowercaseString] rangeOfString:@".gif"];//檢查是否是gif NSData* data = [NSData dataWithContentsOfFile:[key stringByReplacingOccurrencesOfString:@"file://" withString:@""]]; NSString *base64 = [data base64EncodedStringWithOptions:0]; BOOL isGif = (range.location != NSNotFound); if (!isGif) { js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/jpeg;base64,%@')",obj,base64]; }else{ js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/gif;base64,%@')",obj,base64]; } [NSThread excuteInMainThread:^{ [webView stringByEvaluatingJavaScriptFromString:js]; } async:false]; } }]; }
3.回調webView頁面,用本地鏈接替換原有的圖片
加載已下載好的圖片,這里主要通過js來實現,即第2步中的replaceWebPImg方法,該js方法可通過提前置于html的模板中,或者webViewDidFinishLoad后采用js注入進去
replaceWebPImg = function(src, localPath) { var imgs = document.querySelectorAll('img[osrc="'+src+'"]'),len = imgs.length;; for (var i = 0; i < len; i++) { var img = imgs[i]; img.src = localPath; } }
好再次總結一下整個流程:
這篇寫的比較簡單,更詳細的步驟請查閱上面的代碼,里面我加上還算詳細的注釋,希望對想要在webView中使用webp圖片的大家有所幫助。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。