iOS极简模式实现Webview网页图片原生预览

iOS极简模式实现Webview网页图片原生预览_第1张图片
温暖.jpg

前言

最近的几个项目中都需要加载大量的HTML,需要将HTML中的图片在点击时实现原生预览。由于HTML的来源很复杂,包括有后台框架编辑的、第三方提供的、网络抓取的等等。所以只能采取获取HTML之后前端注入JS事件来触发图片点击事件,获取当前页面的所有图片地址。由于实现的原理很简单(两行代码),就不需要使用JavaScriptCore或者其他第三方框架了。

实现效果

HTMLImage.gif
框架整体介绍
  • 该框架为一个通用HTML图片预览框架,旨在提供一种简单快捷的调用方式来native预览网页图片。
  • 同时支持UIWebView与WKWebView。
  • 支持网页图片自定义过滤规则。过滤“头像、广告”之类的小图标。
  • 支持用户自定义核心抓取图片JS、自定义解析规则。
  • 支持配置参数确定是否仅抓取正文(conent)部分图片。
  • SDK支持解析懒加载类型HTML网页(ps:更新以后图片加载就是采用的滚动加载模式)

实现原理

  • HTML加载完成之后注入图片点击的JS。
  • 截取JS的点击事件并拆分出所有图片URL和当前点击图片URL。
  • 通过OPTION配置项、配置相关业务参数。
  • 自动解析懒加载类型HTML网页、允许用户自定义懒加载核心属性。
注入图片点击JS需要完成的功能
  • 点击图片能够响应图片的点击事件。
  • 能够获取当前点击图片的URL。
  • 能够获取当前HTML中的所有图片URL。
  • 能够将图片点击事件与网页自带点击事件区分开来。
  • 能够将当前点击图片URL与所有图片URL区分开来。
截取JS的点击事件解析URL
  • 根据标识符判断点击是否执行图片预览功能
  • 根据分隔符拆分当前点击图片URL与所有图片URL。
  • 根据分隔符将所有图片URL合并成图片数组。
  • 具体业务过滤不合法图片URL(eg:包含logo等)。
核心JS代码实现
// 通知 iPhone UIWebView 加载 url 对应的资源
//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);
    // 发起请求后这个 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
截取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];
        //当前实际点击图片的地址
        NSString *indexImageURL = [mixURLArray lastObject];
    }

实际项目中遇到的问题

  • HTML来源与展示界面比较复杂,无法统一WebView界面。导致以上代码需要重复调用多次。
  • HTML的格式比较奇葩,鬼知道后台使用的什么转换器。
  • 图片地址命名会出现与分隔符冲突等等。
  • HTML中混杂了小图标(logo、头像等)需要过滤。
封装JS与URL解析

为了避免重复调用,快速实现功能。对上述功能做了简单的封装。

  • UIWebView实现以下两行代码即可
-(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实现以下两行代码
-(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];
  • 仅加载标准正文content中的所有图片(例如中正文文章中所有图片),增加了过滤条件OPTION_StandardCoreJS。
self.htmlSDK = [ZWHTMLSDK zw_loadStandardBridgeJSWebview:webView];
  • 如果以上还是不能满足需求,需要过滤更多的HTML图片信息,则需要自定义option过滤器。eg:仅加载正文HTML图片、过滤掉所有图片URL包含有logo、avaters的图片。
ZWHTMLOption *option = [[ZWHTMLOption alloc] init];
  option.getAllImageCoreJS = OPTION_StandardCoreJS;
  option.filterURL = @[@"logo",@"avaters"];
  self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView withOption:option];
  • 需要加载执行自定义的JS
ZWHTMLOption *option = [[ZWHTMLOption alloc] init];
  option.zwPreviewJS = @"自定义的JS";
  self.htmlSDK = [ZWHTMLSDK zw_loadBridgeJSWebview:webView withOption:option];

图片预览显示

  • 按照上面两行代码实现调用即可预览显示。SDK内部已经封装了图示的显示模式。
//预览视图、已集成SDK中
ZWPreviewImageView *showView = [ZWPreviewImageView showImageWithArray:allImageArray withShowIndex:index];
[showView showRootWindow];
  • 如果用户需要自定义(嫌弃>_<)图片浏览器,只需要实现调用以下的block。allImageArray:过滤后所有URL数组。index:当前操作图片的序号。
self.htmlSDK.blockHandlePreview = ^(NSArray *allImageArray, NSInteger index) {
        //自定义图片预览
    };

如何使用SDK

强烈建议您使用pod导入,节省导入依赖的时间。

  • 使用cocoaPods导入(搜索不到请更新本地仓库)
pod 'ZWHTMLImage',       '~> 0.0.2'
  • 直接将文件ZWHTMLImage拖入工程中

依赖ZWPhotoPreview图片显示框架。

#import "ZWHTMLSDK.h"

关于图片保存权限

  • 长按保存功能需要用户info.plist中配置权限
Privacy - Photo Library Additions Usage Description

源码

源码放在GitHub上,欢迎指正,记得star哦!

v0.0.2版本更新记录

  • 【新增】: 支持懒加载类型网页图片的读取功能。

  • 【修改】: 重新构造图片预览功能、更新图片预览框架ZWPhotoPreview最新版本。

  • 【新增】: 提供图片快速预览、手势拖放动画、手势缩放、长按保存、页码选择等最新功能。

v0.0.1版本更新记录

  • 【新增】: 提供简便的HTML图片放大预览功能。
  • 【新增】: 提供简便的HTML图片过滤功能、用户自定义过滤参数。
  • 【新增】: cocoapods支持。

你可能感兴趣的:(iOS极简模式实现Webview网页图片原生预览)