对当前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];
}