iOS-长截图 (学习记录)

前言

长截图 —— 也就是可以截到超出屏幕的长图。在实现长图之前,我们先要了解一下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);
    }];
}
  1. 为了让用户看不到我们截图滚动的操作,这里使用snapshotViewAfterScreenUpdates 方法来实现屏幕快照进行遮盖。
  2. 初始化imgArr数组,之后用来存放每一部分截图。
  3. 保存当前WKScrollView.contentOffset以便截图操作结束后还原“案发现场”。
  4. 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);
        }
    }
}

  1. 判断当前scrollView是否已经滚动到底部。
  2. 如果没滚动到底部,则再次设置scrollView.contentOffset到下一页进行截图。
  3. 这边给截图添加延迟,保证页面完全加载。截好的图片将放入数组。
  4. 如果scrollView已经到底部,则用一个容器视图,将所有的截图拼接并且展示。
  5. 最后再对容器视图进行截图操作,便可以得到完整的WKWebView页面截图了。

End

这个方法还是存在一定的问题,如果有大佬知道如何解决悬浮栏多次被截问题,请回复我~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值