简体   繁体   English

UIWebView到UIImage

[英]UIWebView to UIImage

I tried to capture image from UIWebView using this method but the image contains only visible area of the screen. 我尝试使用此方法从UIWebView捕获图像,但图像仅包含屏幕的可见区域。 How do I capture full content of UIWebView including invisible areas, ie the entire web page into one single image? 如何捕获包含不可见区域的UIWebView的完整内容,即将整个网页合并为一个单独的图像?

-(UIImage*)captureScreen:(UIView*) viewToCapture{
  UIGraphicsBeginImageContext(viewToCapture.bounds.size);
  [viewToCapture.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return viewImage;
}

Check this out Rendering a UIWebView into an ImageContext 检查一下将UIWebView渲染到ImageContext中

or just use this :) : 或者只是使用这个:):

    (UIImage*) imageFromWebview:(UIWebView*) webview{

//store the original framesize to put it back after the snapshot
CGRect originalFrame = webview.frame;

//get the width and height of webpage using js (you might need to use another call, this doesn't work always)
int webViewHeight = [[webview stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"] integerValue];
int webViewWidth = [[webview stringByEvaluatingJavaScriptFromString:@"document.body.scrollWidth;"] integerValue];

//set the webview's frames to match the size of the page
[webview setFrame:CGRectMake(0, 0, webViewWidth, webViewHeight)];

//make the snapshot
UIGraphicsBeginImageContextWithOptions(webview.frame.size, false, 0.0);
[webview.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//set the webview's frame to the original size
[webview setFrame:originalFrame];

//and VOILA :)
return image;
}

EDIT (from a comment by Vad ) 编辑 (来自Vad的评论)

Solution was to call 解决方案是打电话

webView.scalesPageToFit = YES;

in the initialization, and 在初始化中,和

[webView sizeToFit]

when the page did finish loading. 当页面完成加载。

You are currently capturing only the visible part because you are limiting the image context to what's visible. 您当前只捕获可见部分,因为您将图像上下文限制为可见部分。 You should limit it to what's available. 你应该把它限制在可用的范围内。

UIView has a scrollView property that has contentSize , telling you what is the size of the web view inside the scroll view. UIView有一个scrollView属性,它有contentSize ,告诉你滚动视图中Web视图的大小是多少。 You can use that size to set your image context like this: 您可以使用该大小来设置图像上下文,如下所示:

-(UIImage*)captureScreen:(UIView*) viewToCapture{
    CGSize overallSize = overallSize;
    UIGraphicsBeginImageContext(viewToCapture.scrollView.contentSize);
    // Save the current bounds
    CGRect tmp = viewToCapture.bounds;
    viewToCapture.bounds = CGRectMake(0, 0, overallSize.width, overallSize.height);
    // Wait for the view to finish loading.
    // This is not very nice, but it should work. A better approach would be
    // to use a delegate, and run the capturing on the did finish load event.
    while (viewToCapture.loading) {
         [NSThread sleepForTimeInterval:0.1];
    }
    [viewToCapture.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    // Restore the bounds
    viewToCapture.bounds = tmp;
    return viewImage;
}

EDIT : New answer from me with tested code. 编辑 :测试代码的新答案。

Add below method to capture UIWebView into UIImage . 添加以下methodUIWebView captureUIImage It will also capture unvisible area as well. 它也将捕获不unvisible area

- (UIImage*)webviewToImage:(UIWebView*)webView
{
  int currentWebViewHeight = webView.scrollView.contentSize.height;
  int scrollByY = webView.frame.size.height;

  [webView.scrollView setContentOffset:CGPointMake(0, 0)];

  NSMutableArray* images = [[NSMutableArray alloc] init];

  CGRect screenRect = webView.frame;

  int pages = currentWebViewHeight/scrollByY;
  if (currentWebViewHeight%scrollByY > 0) {
      pages ++;
  } 

  for (int i = 0; i< pages; i++)
  {
    if (i == pages-1) {
        if (pages>1)
            screenRect.size.height = currentWebViewHeight - scrollByY;
    }

    if (IS_RETINA)
        UIGraphicsBeginImageContextWithOptions(screenRect.size, NO, 0);
    else
        UIGraphicsBeginImageContext( screenRect.size );
    if ([webView.layer respondsToSelector:@selector(setContentsScale:)]) {
        webView.layer.contentsScale = [[UIScreen mainScreen] scale];
    }
    //UIGraphicsBeginImageContext(screenRect.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);

    [webView.layer renderInContext:ctx];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if (i == 0)
    {
        scrollByY = webView.frame.size.height;
    }
    else
    {
        scrollByY += webView.frame.size.height;
    }
    [webView.scrollView setContentOffset:CGPointMake(0, scrollByY)];
    [images addObject:newImage];
  }

  [webView.scrollView setContentOffset:CGPointMake(0, 0)];

  UIImage *resultImage;

  if(images.count > 1) {
    //join all images together..
    CGSize size;
    for(int i=0;i<images.count;i++) {

        size.width = MAX(size.width, ((UIImage*)[images objectAtIndex:i]).size.width );
        size.height += ((UIImage*)[images objectAtIndex:i]).size.height;
    }

    if (IS_RETINA)
        UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    else
        UIGraphicsBeginImageContext(size);
    if ([webView.layer respondsToSelector:@selector(setContentsScale:)]) {
        webView.layer.contentsScale = [[UIScreen mainScreen] scale];
    }
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);

    int y=0;
    for(int i=0;i<images.count;i++) {

        UIImage* img = [images objectAtIndex:i];
        [img drawAtPoint:CGPointMake(0,y)];
        y += img.size.height;
    }

    resultImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
  } else {

    resultImage = [images objectAtIndex:0];
  }
  [images removeAllObjects];
  return resultImage;
}

Also add these macro for checking if iOS is retina display 还要添加这些macro以检查iOS是否是retina显示

#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM