序曲客栈


小店重新开张不久,主营 iOS 各类干活,Nodejs/Android/PS/PM 随机供货,小二十分偷懒,客官请自便。 ----欢迎勾搭╮( ̄▽ ̄)╭


我是如何一步一步获取UIWebView内图片及放大查看的

起因

最近整理项目发现以前项目里面有一个类似于XX头条 UIWebView 内图片点击渐变放大查看的效果,但是图片的相对于 Window 的坐标不正确导致放大动画的起始位置被迫每次从 Window 中间开始。于是,我决定找到动画的起始位置。

整体思路

从 'UIWebView' 获取图片地址,然后下载并缓存图片,最后利用这张图做动画。

  • UIWebView 添加 UITapGestureRecognizer
  • 获取图片的绝对坐标
  • 获取图片URL
  • 缓存图片
  • 利用 UIImageView 绘制“覆盖图”,
  • 利用覆盖图实现放大查看效果

依赖的三方库

  • SDWebImage,用来缓存图片
  • JTSImageViewController,用来查看图片的三方库,支持渐变查看,双击放大,滑动消失

主要技术

通过调用 UIWebViewstringByEvaluatingJavaScriptFromString 方法向UIWebView注入JS脚本,并将返回结果以字符串的方式返回。但是值得注意的是,这个方法不能直接返回HTML DOM Element 对象,只能返回对象属性值。 例如,返回 documenttitle,

[webview stringByEvaluatingJavaScriptFromString:@"window.title"]

过程

添加UITapGestureRecognizer

因为 UIWebView 有一个属性是 UIScrollView,导致 UIWebView 无法直接响应 UITapGestureRecognizer。经过查阅文档,苹果规定默认情况下,两个手势识别器是无法同时识别他们的不同手势的。解决方法是实现 UITapGestureRecognizerdgestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 协议方法,并返回YES,一般情况下这个手势能够保证UITapGesture能够被识别。

获取图片的绝对坐标

首先“图片”是一个HTML DOM Element 对象,有以下几个相关的属性:

  • element.offsetHeight 返回元素的高度。
  • element.offsetWidth 返回元素的宽度。
  • element.offsetLeft 返回元素的水平偏移位置。
  • element.offsetParent 返回元素的偏移容器。
  • element.offsetTop 返回元素的垂直偏移位置。

还有Window对象,表示浏览器中打开的窗口,相关属性:

  • pageXOffset 设置或返回当前页面相对于窗口显示区左上角的 X 位置。
  • pageYOffset 设置或返回当前页面相对于窗口显示区左上角的 Y 位置。

“绝对坐标”是指当前 UIWindow 内,UIWebView 停止滑动状态下,图片对象相对于 UIWindow 的坐标,等价于iOS中 UISrollView 图片相对于根控制器视图的位置。

X = element.offsetLeft - pageXOffset  
Y = element.offsetTop - pageYOffset  

获取图片URL

根据直接传入 touch 点的坐标获取 Element 元素对象 src 属性的值,并解析出正确的图片地址。

- (NSString*)elementImgUrlWithPoint:(CGPoint)pt{
    NSString *jsString = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", pt.x, pt.y];
    NSString *imgUrl = [self stringByEvaluatingJavaScriptFromString:jsString];
    NSString *fileType = [[imgUrl componentsSeparatedByString:@"."] lastObject];
    if ([fileType isEqualToString:@"png"] || [fileType isEqualToString:@"jpg"]) {
        if (imgUrl.length > 0) {
            return imgUrl;
        }
    }
    return nil;
}

缓存图片

缓存图片有两种初步策略,一是加载网页的时候遍历 UIWebView 内的图片,即时下载并缓存,第二个是方案是当第一次点击图片的时候才开始下载并缓存。两种方案比较,第一种会占用大量存储空间,但是体验效果会很好,第二种在首次查看图片的时候体验效果不好,但是会节省空间。我在这次的项目中使用了 SDWebImage 来加载并缓存图片,这是属于第二种。

利用 UIImageView 绘制“覆盖图”,并利用覆盖图实现放大查看效果

通过前几步的准备拿到了做动画的两个主要因数:一张图片和动画起始位置,然后在手势识别响应方法中生成一个与原始图片完全重合 UIImageView

利用覆盖图实现放大查看效果

至此,要实现这个效果和平常OC代码里实现已经没有差别。实现过程中主要考虑的一点是坐标系转换。这里直接上一个比较成熟的方案 JTSImageViewController,只需将Image和Frame作为参数就可实现。

总结

  • 实现思路并不复杂
  • 难点在于需要对 HTML 基础知识有一定的了解
  • 需要依赖两个三方

最后奉上实现过程PUShark

更早的文章

活在帝都,重新出发

时间起点 今天折腾了一天,终于把我博客找了回来。之前不知道发生了什么,CPU占用维持在30%,导致远程连接响应速度特别慢,所以一气之下把盘给格了。再加上我偷懒没有把数据同步到本地来,所以之前的东西都没…

日记继续阅读