美文网首页iOS 知识点iOS菜鸟联盟
针对WKWebView进行内容的截屏。

针对WKWebView进行内容的截屏。

作者: 走向菜鸟的菜鸟 | 来源:发表于2018-03-21 14:58 被阅读500次

    最近项目中需要截屏分享的功能,之前也了解过iOS截屏的技术,并写了关于截屏的笔记,兴冲冲的拿着代码稍作修改,对WKWebView开始截屏,结果出乎意料,截取了一片黑色🤷‍♀️。
    于是写demo测试代码的可用性,对scrollView进行截屏,答案是没有问题,代码没有问题,于是猜测是webView的问题,赶紧查找资料,这两篇文章【1】--【2】受益匪浅,从而解决了对WKWebView全部内容的截屏。

    原理:UIGraphicsBeginImageContextWithOptions(<#CGSize size#>, <#BOOL opaque#>, <#CGFloat scale#>)
    size——绘制图片的大小
    opaque—透明开关,如果图形完全不用透明,设置为YES以优化位图的存储。
    scale—–缩放因子,[UIScreen mainScreen].scale保持原图分辨率

    使用的方法还是滚动截屏的方式,先计算出要截取几次屏才能够截完webView.scrollView.contentSize.height / webView.bounds.size.height,截取完成一次,调整webView的偏移再进行截屏,以此类推。

    话不多说,直接上代码(文章2对webView的处理比较多,本人对代码进行了截取,完成了截屏的操作):

    + (void)WKWebViewScroll:(WKWebView *)webView CaptureCompletionHandler:(void(^)(UIImage *capturedImage))completionHandler {
        
        // 制作了一个UIView的副本
        UIView *snapShotView = [webView snapshotViewAfterScreenUpdates:YES];
        
        snapShotView.frame = CGRectMake(webView.frame.origin.x, webView.frame.origin.y, snapShotView.frame.size.width, snapShotView.frame.size.height);
        
        [webView.superview addSubview:snapShotView];
        
        // 获取当前UIView可滚动的内容长度
        CGPoint scrollOffset = webView.scrollView.contentOffset;
        
        // 向上取整数 - 可滚动长度与UIView本身屏幕边界坐标相差倍数
        float maxIndex = ceilf(webView.scrollView.contentSize.height/webView.bounds.size.height);
        
        // 保持清晰度
        UIGraphicsBeginImageContextWithOptions(webView.scrollView.contentSize, false, [UIScreen mainScreen].scale);
        
        NSLog(@"--index--%d", (int)maxIndex);
        
        // 滚动截图
        [self ZTContentScroll:webView PageDraw:0 maxIndex:(int)maxIndex drawCallback:^{
            UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            
            // 恢复原UIView
            [webView.scrollView setContentOffset:scrollOffset animated:NO];
            [snapShotView removeFromSuperview];
            
    //        UIImage *resultImg = [UIImage imageWithData:UIImageJPEGRepresentation(capturedImage, 0.5)];
            
            completionHandler(capturedImage);
            
        }];
    }
    
    // 滚动截图
    + (void)ZTContentScroll:(WKWebView *)webView PageDraw:(int)index maxIndex:(int)maxIndex drawCallback:(void(^)(void))drawCallback{
        [webView.scrollView setContentOffset:CGPointMake(0, (float)index * webView.frame.size.height)];
        CGRect splitFrame = CGRectMake(0, (float)index * webView.frame.size.height, webView.bounds.size.width, webView.bounds.size.height);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [webView drawViewHierarchyInRect:splitFrame afterScreenUpdates:YES];
            if(index < maxIndex){
                [self ZTContentScroll:webView PageDraw: index + 1 maxIndex:maxIndex drawCallback:drawCallback];
            }else{
                drawCallback();
            }
        });
    }
    

    延伸:如何在对WKWebView截屏之后的图片顶部或底部进行添加视图?
    1️⃣:如果添加的视图是单纯的一张图片(将img1添加到img2的顶部):

    // 定义拼接后图片的宽度
    CGFloat w = img1.size.width;
    // 定义拼接后图片的高度
    CGFloat h = img1.size.height + img2.size.height;
    // 根据size定义画布大小,分辨率,开始绘制
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), false, [UIScreen mainScreen].scale);
    // 将img1先绘制到画布上
    [img1 drawInRect:CGRectMake(0, 0, img1.size.width, img1.size.height)];
    // 再讲img2绘制到画布上,位置在img1的下方
    [img2 drawInRect:CGRectMake(0, img1.size.height, img2.size.width, img2.size.height)];
    // 通过画布获得图片
    UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
    // 结束绘制
    UIGraphicsEndImageContext();
    

    2️⃣:如果添加的视图是一个自定义的视图view:
    思路:先将视图view添加到webView的顶部,在对WKWebView进行截屏。

    // 视图添加到webView的底部,设置底部的偏移为视图的高度
    _webView.scrollView.contentInset = UIEdgeInsetsMake(0, 0, img.size.height, 0);
    // 视图添加到webView的顶部,设置顶部的偏移为视图的高度
    // _webView.scrollView.contentInset = UIEdgeInsetsMake(img.size.height, 0, 0, 0);
    // 设置放在底部的frame
    CustomerView *view = [[CustomerView alloc] initWithFrame:CGRectMake(0, _webView.scrollView.contentSize.height, _webView.bounds.size.width, img.size.height)];
    // 设置放在顶部的frame
    // CustomerView *view = [[CustomerView alloc] initWithFrame:CGRectMake(0, -img.size.height, _webView.bounds.size.width, img.size.height)];
    // 添加到webView的scrollView上
    [_webView.scrollView addSubview:view];
    

    截屏代码修改:


    截屏.png
    滚动截屏代码.png

    相关文章

      网友评论

        本文标题:针对WKWebView进行内容的截屏。

        本文链接:https://www.haomeiwen.com/subject/fdjgqftx.html