7

このメソッドを使用して UIWebView から画像をキャプチャしようとしましたが、画像には画面の可視領域しか含まれていません。非表示領域を含む UIWebView の完全なコンテンツ、つまり Web ページ全体を 1 つの画像にキャプチャするにはどうすればよいですか?

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

3 に答える 3

6

これをチェックしてくださいRendering a UIWebView into an ImageContext

またはこれを使用してください:):

    (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;
}
于 2014-02-19T16:07:19.297 に答える
4

EDIT ( Vadのコメントから)

解決策は電話することでした

webView.scalesPageToFit = YES;

初期化中、および

[webView sizeToFit]

ページの読み込みが完了したとき。

画像のコンテキストを表示されているものに制限しているため、現在、表示されている部分のみをキャプチャしています。利用可能なものに限定する必要があります。

UIViewには has というscrollViewプロパティがありcontentSize、スクロール ビュー内の Web ビューのサイズを示します。そのサイズを使用して、次のように画像コンテキストを設定できます。

-(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;
}
于 2012-08-20T15:31:30.270 に答える
1

編集:テスト済みのコードを使用した私からの新しい回答。

methodに以下を追加capture UIWebViewしますUIImage。こちらも捕獲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;
}

また、表示されているmacroかどうかを確認するためにこれらを追加しますiOSretina

#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))
于 2012-08-20T15:31:49.647 に答える