ios Webview截图总结

对当前view可见区域截屏

   UIGraphicsBeginImageContextWithOptions(CGSizeMake(CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)), YES, 0.0);
[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

关键api详细解

UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) :开启一个绘图的上下文

  • size : size是指绘图上下文的宽高,可以理解为要绘制图形的画布的大小
  • opaque : 是否透明,如果传YES,画布的背景色为黑色,NO的时候,画布背景色是白色
  • scale:指的是绘制出来的图片的像素比,决定了绘图图片的清晰度,一般填0.0,默认屏幕缩放比

- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates: 将要截屏的view绘制到当前的上下文中。

rect:指定图片绘制的坐标
afterUpdates:截图的瞬间是否将屏幕当前的变更渲染进去
这个方法的是UIView的方法,截图的目标对象就是当前方法的调用者。
例如[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO]; 就是对self.view这个对象进行截图,会把self.view 当前的这个view全部截取下来然后绘制到当前的上下文中生成图片,然后按照这个方法中指定的rect 为frame,以画布为父视图绘制到画布中去。
注意:截图截取的是drawViewHierarchyInRect这个方法调用的view,而渲染出来的效果(图片的位置和大小)是由UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)中的size和- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates中的rect共同决定的。

裁剪图片

- (UIImage *)createImageWithRect:(CGRect)rect image:(UIImage *)clipImage {
    rect.origin.x *= clipImage.scale;
    rect.origin.y *= clipImage.scale;
    rect.size.width *= clipImage.scale;
    rect.size.height *= clipImage.scale;
    CGImageRef imageRef = CGImageCreateWithImageInRect(clipImage.CGImage, rect);
    UIImage *image = [UIImage imageWithCGImage:imageRef scale:clipImage.scale orientation:UIImageOrientationUp];
    CGImageRelease(imageRef);
    return image;
}

WKWebview截图

对于WKWebView使用 renderInContext的方法进行截图的时候, 当WKWebView 执行UIGraphicsGetCurrentContext()的结果返回的nil,截图失败

所以只能UIView的drawViewHierarchyInRect的方法去截图

UIWebView截图

初始版:

- (void)snapshotForScrollView:(UIScrollView *)scrollView
{
    // 1. 记录当前 scrollView 的偏移和位置
    CGPoint currentOffset = scrollView.contentOffset;
    CGRect currentFrame = scrollView.frame;

    scrollView.contentOffset = CGPointZero;
    // 2. 将 scrollView 展开为其实际内容的大小
    scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);

    // 3. 第三个参数设置为 0 表示设置为屏幕的默认缩放因子
    UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, YES, 0);
    [scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    // 4. 重新设置 scrollView 的偏移和位置,还原现场
    scrollView.contentOffset = currentOffset;
    scrollView.frame = currentFrame;
}

目前我所用的版本

__block UIImage* snapshotImage = nil;
    
    UIView *snapShotMaskView;
    if (needMask){
        snapShotMaskView = [self addSnapShotMaskView];
        addMaskAfterBlock?addMaskAfterBlock():nil;
    }
    
    //保存offset
    CGPoint oldContentOffset = self.contentOffset;
    //保存frame
    CGRect oldFrame = self.frame;

    NSLog(@"contentSize1 =%@",NSStringFromCGSize(self.contentSize));
    if (self.contentSize.height > self.frame.size.height) {
        //拖动到最后一屏,确保页面全部被加载出来
        self.contentOffset = CGPointMake(0, self.contentSize.height - self.frame.size.height);
    }
    NSLog(@"contentSize2 =%@",NSStringFromCGSize(self.contentSize));
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(300 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
        self.layer.frame = CGRectMake(0, 0, self.contentSize.width, self.contentSize.height);
        
        self.contentOffset = CGPointZero;
        
        NSLog(@"contentSize3 =%@",NSStringFromCGSize(self.contentSize));
    });
    
    //延迟0.3秒,避免有时候渲染不出来的情况
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(900 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
       
        NSLog(@"contentSize4 =%@",NSStringFromCGSize(self.contentSize));
        UIGraphicsBeginImageContextWithOptions(self.contentSize,YES,[UIScreen mainScreen].scale);
//self.bounds.size
        CGContextRef context = UIGraphicsGetCurrentContext();

        [self.layer renderInContext:context];

        //[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];

        snapshotImage = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

        self.layer.frame = oldFrame;
        //还原
        self.contentOffset = oldContentOffset;
        
        if (snapShotMaskView.layer){
            [snapShotMaskView.layer removeFromSuperlayer];
        }

备选方案

https://github.com/startry/SwViewCapture

你可能感兴趣的:(ios Webview截图总结)