以前使用UIWebview时,想截取整个页面,可以调整内部scrollView的frame,之后调用 scrollView的layer的 render 方法,很方便。

但是在WKWebView上,行不通。

我觉得以前的UIWebview其实是把整个页面都渲染在内存中,只是我们看不到。而WKWebView为了优化内存,只渲染WKWebView的Frame大小的内容。

所以想用WKWebview截取整个页面,必须放大WKWebview的frame。

 webView.frame = CGRect(x: , y: , width: webView.scrollView.frame.size.width, height: webView.scrollView.contentSize.height);

改变了frame之后,我们就可以利用scrollView.layer.render 去渲染整个页面了。

但是这时候又出现了另一个问题:  渲染网页是需要时间的,把webview的frame扩大后,我们不知道什么时候,系统完成了渲染。比如下面这个例子:

@IBAction func takeScreenshot(){

        webView.frame = CGRect(x: , y: , width: webView.scrollView.frame.size.width, height: webView.scrollView.contentSize.height);

            let scrollView = self.webView.scrollView

            UIGraphicsBeginImageContextWithOptions(self.webView.scrollView.contentSize,false, UIScreen.main.scale)

            scrollView.layer.render(in: UIGraphicsGetCurrentContext()!)

            let image = UIGraphicsGetImageFromCurrentImageContext()

            let pngData = UIImagePNGRepresentation(image!);

            let dstPath = NSHomeDirectory()+"/Documents/test.png"
let dstUrl = URL(fileURLWithPath: dstPath)
do{
try pngData?.write(to: dstUrl, options: .atomicWrite)
}catch{ } print("dest is %@",dstUrl); UIGraphicsEndImageContext()
}

由于立即调用了截图函数,webView没有足够的时间渲染,只多渲染了一小部分。

之后,我用下面的代码进行测试,注意,这里延时了0.3s,给了webview一定的渲染时间:

    @IBAction func takeScreenshot(){

        webView.frame = CGRect(x: , y: , width: webView.scrollView.frame.size.width, height: webView.scrollView.contentSize.height);

        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.3) {
let scrollView = self.webView.scrollView UIGraphicsBeginImageContextWithOptions(self.webView.scrollView.contentSize,false, UIScreen.main.scale) scrollView.layer.render(in: UIGraphicsGetCurrentContext()!) let image = UIGraphicsGetImageFromCurrentImageContext() let pngData = UIImagePNGRepresentation(image!); let dstPath = NSHomeDirectory()+"/Documents/test.png"
let dstUrl = URL(fileURLWithPath: dstPath)
do{
try pngData?.write(to: dstUrl, options: .atomicWrite)
}catch{ } print("dest is %@",dstUrl); UIGraphicsEndImageContext()
} }

下面是结果的截图,一切正常:

那么,如果网页更长,0.3秒一定也不够用,我们怎么知道该延时多少呢?

这时候我又发现了一个函数,是属于UIView的,drawHierarchy,根据api描述,第二个参数好像和渲染有关,能不能解决我们的问题呢,继续测试:

 @IBAction func takeScreenshot(){

        webView.frame = CGRect(x: , y: , width: webView.scrollView.frame.size.width, height: webView.scrollView.contentSize.height);

            let scrollView = self.webView.scrollView

            UIGraphicsBeginImageContextWithOptions(self.webView.scrollView.contentSize,false, UIScreen.main.scale)

            self.webView.drawHierarchy(in: CGRect(x: 0, y: 0, width: self.webView.scrollView.frame.size.width, height: self.webView.scrollView.contentSize.height), afterScreenUpdates: true)

            let image = UIGraphicsGetImageFromCurrentImageContext()

            let pngData = UIImagePNGRepresentation(image!);

            let dstPath = NSHomeDirectory()+"/Documents/test.png"
let dstUrl = URL(fileURLWithPath: dstPath)
do{
try pngData?.write(to: dstUrl, options: .atomicWrite)
}catch{ } print("dest is %@",dstUrl); UIGraphicsEndImageContext() }

结果还是不行,效果和使用layer的render方法一样!看来afterScreenUpdates这个参数跟网页的渲染无关了。

那么把Webview frame直接扩大为html内容的大小并截图的方式其实是很有问题的,截图时机不好掌握, 内存和cpu的占用也会很大。

这里要推荐一个github上的项目,https://github.com/startry/SwViewCapture, 它的解决思路如下:

1. 截图时机的掌握:每次通过调整视图frame,只渲染一屏的截图,速度很快,只需稍为延迟,即可保证完美截图。

2.内存和cpu:由于每次只处理一屏幕的截图,内容很少,对cpu和内存的冲击都很小。

下面贴出其中的关键代码:

 fileprivate func swContentPageDraw (_ targetView: UIView, index: Int, maxIndex: Int, drawCallback: @escaping () -> Void) {

        // set up split frame of super view
let splitFrame = CGRect(x: , y: CGFloat(index) * targetView.frame.size.height, width: targetView.bounds.size.width, height: targetView.frame.size.height)
// set up webview frame
var myFrame = self.frame
myFrame.origin.y = -(CGFloat(index) * targetView.frame.size.height)
self.frame = myFrame DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in targetView.drawHierarchy(in: splitFrame, afterScreenUpdates: true) if index < maxIndex {
self.swContentPageDraw(targetView, index: index + , maxIndex: maxIndex, drawCallback: drawCallback)
}else{
drawCallback()
}
}
}

用WKWebView 截取整个Html页面的更多相关文章

  1. iOS开发WKWebView 返回H5上级页面

    #pragma mark ---- 点击事件 -(void)leftTapClick:(UITapGestureRecognizer *)sender{ //判断是否能返回到H5上级页面 if (se ...

  2. WKWebView与JavaScript交互基础

    login.html 代码 <!DOCTYPE html> <html> <head> <title>使用JavaScript</title> ...

  3. iOS-JavaScript向WKWebView传值

    一.本地代码所需操作 1.创建viewController并遵守协议 @interface ViewController ()<WKNavigationDelegate,WKScriptMess ...

  4. 微信iOS WKWebview 网页开发适配指南

    微信iOS客户端将于2017年3月1日前逐步升级为WKWebview内核,需要网页开发者提前做好网站的兼容检查和适配. 背景 WKWebView 是苹果在iOS 8中引入的新组件,目的是提供一个现代的 ...

  5. EL表达式处理字符串 是否 包含 某字符串 截取 拆分...............

    EL表达式处理字符串 是否 包含 某字符串 截取 拆分............... JSP页面页头添加<%@ taglib uri="/WEB-INF/taglib/c.tld&qu ...

  6. iOS WKWebview 网页开发适配指南【转】

    微信iOS客户端将于2017年3月1日前逐步升级为WKWebview内核,需要网页开发者提前做好网站的兼容检查和适配.如有问题,可参考文末联系方式,向我们咨询. 背景 WKWebView 是苹果在iO ...

  7. phantomJs页面截图

    因为phantomjs使用了一个真正的渲染引擎WebKit,它能截取一个web页面的真实影像,这是因为phantomjs能够折射出WEB页面上的任何东西,包括html,css,svg和Canvas等. ...

  8. iOS WKWebview 网页开发适配指南

    iOS WKWebview 网页开发适配指南 微信iOS客户端将于2017年3月1日前逐步升级为WKWebview内核,需要网页开发者提前做好网站的兼容检查和适配.如有问题,可参考文末联系方式,向我们 ...

  9. 网易严选的wkwebview测试之路

    本文来自网易云社区 作者:孙娇 UIWebView是苹果继承于UIView封装的一个加载web内容的类,它可以加载任何远端的web数据展示在你的页面上,你可以像浏览器一样前进后退刷新等操作.不过苹果在 ...

随机推荐

  1. 【Swift】iOS开发笔记(一)

    前言 边开发边学习,边攒经验,汇总一下记录到这里 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯伯: http://over140.cnblog ...

  2. 软工+C(1): 题目设计、点评和评分

    // 下一篇:分数和checklist 如何设计题目 教学中的一个问题是老师出题太简单了,题目设计一开始上来就不紧凑,我认为一个好的课程应该上来就给你紧凑感,而不是先上来"轻松2-3周&qu ...

  3. eclipse(STS)安装jd-eclipse插件实现查看API源代码功能

    emmm,IDEA确实是比STS智能很多,不过适当的转化也是需要的,这里介绍一下eclipse(STS)实现查看class反编译的源文件的功能 去Java Decompiler官网下一下eclipse ...

  4. Python学习之路——函数的参数分类

    今日内容 '''实参:调用函数,在括号内传入的实际值,值可以为常量.变量.表达式或三者的组合​*****形参:定义函数,在括号内声明的变量名,用来接受外界传来的值​'''​'''注:形参随着函数的调用 ...

  5. Django之ContentType组件

    一.理想表结构设计 1.初始构建 1. 场景刚过去的双12,很多电商平台都会对他们的商品进行打折促销活动的,那么我们如果要实现这样的一个场景,改如何设计我们的表? 2. 初始表设计 注释很重要,看看吧 ...

  6. P4610 [COCI2011-2012#7] KAMPANJA

    题目背景 临近选举,总统要在城市1和城市2举行演讲.他乘汽车完成巡回演讲,从1出发,途中要经过城市2,最后必须回到城市1.特勤局对总统要经过的所有城市监控.为了使得费用最小,必须使得监控的城市最少.求 ...

  7. C++ Under the Hood

    The original article is taken from http://msdn.microsoft.com/archive/en-us/dnarvc/html/jangrayhood.a ...

  8. Linux端口被占用的解决(附Python专版)

    先说一般情况的解决: lsof -i:8000 查出PID,然后 kill掉程序,接着就可以了 软件重启之后绑定没有释放,lsof -i:8080也查不出来占用的情况 再来个长连接版Python解决法 ...

  9. nginx安装访问

    依赖包安装: 安装gcc gcc-c++: yum -y install gcc gcc-c++ autoconf automake 安装pcre: yum -y install pcre pcre- ...

  10. HDU2859 Phalanx (动态规划)

    Today is army day, but the servicemen are busy with the phalanx for the celebration of the 60th anni ...