iOS-长截图 (学习记录)
短信预约 -IT技能 免费直播动态提醒
目录
前言
长截图 —— 也就是可以截到超出屏幕的长图。在实现长图之前,我们先要了解一下iOS的绘制普通截图操作。在此基础上,来实现长截图。
iOS — 绘制截图
UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale); [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
UIGraphicsBeginImageContextWithOptions
该函数开始创建图片上下文,它有三个参数:
size
:想要渲染图片的大小尺寸
opaque
:所要创建图片的背景是否是不透明的。YES 背景则为黑色,NO 背景则为透明。
scale
:所要创建图片的缩放比例。如果设置为0 ,则和[UIScreen mainScreen].scale
效果一样,随着手机屏幕分辨率改变。- 调用方法
renderInContext
:将view的layer渲染到当前的绘制的上下文中。(Renders the layer and its sublayers into the specified context.) UIGraphicsGetImageFromCurrentImageContext
:基于当前位图的上下文返回图像。UIGraphicsEndImageContext
:从堆栈顶部删除当前基于位图的图形上下文。
以上就是iOS的截图代码了。但是对于WKwebVIew(长图)来说,这个代码截不了完整的图片。因为WKwebView考虑到性能问题,并不会加载用户看不到的地方,所以会导致截图不完整。
WKWebView长截图
思路
这边先来说一下思路吧,我也是参考了网上很多实现方法总结的。我们可以看到WKWebView
中有个子视图是WKScrollView
。那么我们就可以通过拖动ScrollView来加载内容,与此同时截下图片。当ScrollView拖动到底之后,将全部截图拼接起来即可。
PS:当页面有悬浮栏时就会出现问题,在每一张截图中均会出现悬浮栏。目前我没有想到可以解决这个问题的方法,但思路大概是让WKwebVIew全部加载出来,然后进行截图。
实现
外部方法
/// 对WKWebView进行长截图(没有规避H5悬浮栏)/// @param webView 需要进行截图的webView/// @param completionHandler 截图完成回调 - (void)snapshotForWKWebView:(WKWebView *)webView CaptureCompletionHandler:(void (^)(UIImage * _Nonnull))completionHandler { //1.添加遮罩层 UIView *snapshotView = [webView snapshotViewAfterScreenUpdates:YES]; snapshotView.frame = webView.frame; [webView.superview addSubview:snapshotView]; //2.初始化数组 self.imgArr = [NSMutableArray array]; //3.进行截图操作 CGPoint savedCurrentContentOffset = webView.scrollView.contentOffset; webView.scrollView.contentOffset = CGPointZero; [self createSnapshotForWKWebView:webView offset:0.0 remainingOffset_y:webView.scrollView.contentSize.height comletionBlock:^(UIImage *snapshotImg) { webView.scrollView.contentOffset = savedCurrentContentOffset; [snapshotView removeFromSuperview]; completionHandler(snapshotImg); }];}
- 为了让用户看不到我们截图滚动的操作,这里使用
snapshotViewAfterScreenUpdates
方法来实现屏幕快照进行遮盖。 - 初始化
imgArr
数组,之后用来存放每一部分截图。 - 保存当前
WKScrollView.contentOffset
以便截图操作结束后还原“案发现场”。 - 将
WKScrollView.contentOffset
设置为CGPointZero,调用截图方法开始截图。
截图操作方法
/// 绘制WKWebView长截图/// @param webView 所需要截图的WebView/// @param offset_y 当前scollView的y偏移量/// @param reOffset_y 剩余scollView的y偏移量/// @param completeBlock 回调块- (void)createSnapshotForWKWebView:(WKWebView *)webView offset:(float)offset_y remainingOffset_y:(float)reOffset_y comletionBlock:(void(^)(UIImage *snapshotImg))completeBlock{ //判断scrollView是否已经滚动到底 if (reOffset_y>0) { //设置 [webView.scrollView setContentOffset:CGPointMake(0, offset_y) animated:NO]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{ //对页面进行截图操作 UIGraphicsBeginImageContextWithOptions(webView.frame.size, YES, [UIScreen mainScreen].scale); [webView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //将截图添加进数组 [self.imgArr addObject:img]; //修改offsetY偏移量 CGFloat newOffset_y = offset_y + webView.scrollView.frame.size.height; CGFloat newReOffset_y = reOffset_y - webView.frame.size.height; [self createSnapshotForWKWebView:webView offset:newOffset_y remainingOffset_y:newReOffset_y comletionBlock:completeBlock]; }); }else { //合成截图为最终截图 UIView * containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, webView.frame.size.width, webView.scrollView.contentSize.height)]; CGFloat originYOfImgView = 0; for (int i = 0; i<self.imgArr.count; i++) { UIImageView * imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, originYOfImgView, webView.frame.size.width, webView.frame.size.height)]; UIImage * img = self.imgArr[i]; imgView.image = img; originYOfImgView += webView.frame.size.height; [containerView addSubview:imgView]; } //添加合成视图 [webView.superview addSubview:containerView]; //处理最终合并截图 UIGraphicsBeginImageContextWithOptions(containerView.frame.size, YES, [UIScreen mainScreen].scale); [containerView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //移除合成视图 [containerView removeFromSuperview]; //返回截图 if (completeBlock) { completeBlock(img); } }}
- 判断当前
scrollView
是否已经滚动到底部。 - 如果没滚动到底部,则再次设置
scrollView.contentOffset
到下一页进行截图。 - 这边给截图添加延迟,保证页面完全加载。截好的图片将放入数组。
- 如果
scrollView
已经到底部,则用一个容器视图,将所有的截图拼接并且展示。 - 最后再对容器视图进行截图操作,便可以得到完整的
WKWebView
页面截图了。
End
这个方法还是存在一定的问题,如果有大佬知道如何解决悬浮栏多次被截问题,请回复我~
来源地址:https://blog.csdn.net/qq_38863196/article/details/126361878
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341