美文网首页
关于webView截取长图问题

关于webView截取长图问题

作者: 小码honey | 来源:发表于2021-02-19 16:59 被阅读0次

    需求背景:由客户端截取webView页面所有内容并生成图片分享或者保存本地

    思路:

    GitHub找到一个第三方的demo(ZSSnapshotKit),经测试功能满足,集成使用
    实现方式就是截取每屏图片拼接

    //在截图之前先将用户看到的当前页面截取下来,作为一张图片挡住接下来所执行的截取操作,
        //并且在执行完截图操作后,将截取的遮盖图片销毁。
        UIImageView *coverImageView = [[UIImageView alloc] initWithFrame:self.frame];
        coverImageView.image = [self takeSnapshotOfVisibleContent];
        coverImageView.backgroundColor = [UIColor redColor];
        [self.superview addSubview:coverImageView];
        [self.superview bringSubviewToFront:coverImageView];
        
        //分页绘制内容到ImageContext
        CGPoint originalOffset = self.contentOffset;
        
        // 当contentSize.height<bounds.height时,保证至少有1页的内容绘制
        NSInteger pageNum = 1;
        if (self.contentSize.height > self.bounds.size.height) {
            pageNum = (NSInteger)floorf(self.contentSize.height / self.bounds.size.height);
        }
        
        UIColor *backgroundColor = self.backgroundColor;
        if (backgroundColor == nil) backgroundColor = UIColor.whiteColor;
        
        UIGraphicsBeginImageContextWithOptions(self.contentSize, YES, 0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        if (context == nil) {
            [coverImageView removeFromSuperview];
            completion(nil);
            return;
        }
        
        CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
        CGContextSetStrokeColorWithColor(context, backgroundColor.CGColor);
        
        [self drawScreenshotOfPageContent:0 maxIndex:pageNum completion:^{
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            self.contentOffset = originalOffset;
            [coverImageView removeFromSuperview];
            if (completion) {
                completion(image);
            }
        }];
    
    
    
    - (void)drawScreenshotOfPageContent:(NSInteger)index maxIndex:(NSInteger)maxIndex completion:(void(^)(void))completion {
        
        [self setContentOffset:CGPointMake(0, index * self.frame.size.height)];
        CGRect pageFrame = CGRectMake(0, index * self.frame.size.height, self.bounds.size.width, self.bounds.size.height);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self drawViewHierarchyInRect:pageFrame afterScreenUpdates:YES];
            if (index < maxIndex) {
                [self drawScreenshotOfPageContent:index+1 maxIndex:maxIndex completion:completion];
            }else {
                if (completion) {
                    completion();
                }
            }
        });
        
    }
    
    问题:

    目前一般的长图都可以截取,但是有吸顶吸底的则会出现一些小问题


    调试的工具按钮截取好几个
    bug:

    经反复测试,当屏幕滑动未停止时,点击截图按钮,截图有问题如下:


    削顶,中间拼接有重叠错乱情况
    解决:

    由于未发现bug复现路径,耽误很长时间复现,后证实只要屏幕滚动未停止,截图就出问题,尝试过修改scrollView坐标,重新定位,不行;所以换个思路,截图之前让scrollView停止滚动(非禁止)

      // 加了这句代码,停止滚动
        [self.webView.scrollView setContentOffset:self.webView.scrollView.contentOffset animated:NO];
        // 开始截图
        [self.webView.scrollView asyncTakeSnapshotOfFullContent:^(UIImage * _Nullable image) {
            [SVProgressHUD dismiss];
            //保存截图到照片
            UIImageWriteToSavedPhotosAlbum(image, self, @selector(completedWithImage:error:context:), NULL);
        }];
    

    结语:

    好了,说到底还就是一句代码的事!

    知识点补充:
    [iOS关于setContentOffset的一些细节问题]

    在UIScrollView,setContentOffset方法的功能是跳转到你指定内容的坐标,
    setContentOffset有两种方法:setContentOffset:和setContentOffset:animated:
    但是两者还是有点差异的:
    setContentOffset:animated: 这种方法,无论animated为YES还是NO, 都会等待scrollView的滚动结束以后才会执行,也就是当isDragging和isDecelerating为YES的时候,会等待滚动完成才执行上面的方法。
    setContentOffset:这种方法则不受scrollView是否正在滚动的限制
    所以上面的方法可以达到暂停scrollView滚动的效果,只有页面静止状态,才能保证截图正常。

    相关文章

      网友评论

          本文标题:关于webView截取长图问题

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