可可:如何渲染视图到图像?

时间:2012-08-14 08:10:11

标签: macos cocoa

我想知道是否有任何方法可以渲染图像?就像截图一样,但我可以为该方法指定任何视图。我知道如何在ios中做到这一点。 Saving view content,但我怎样才能在mac os中完成?

4 个答案:

答案 0 :(得分:15)

有几种方法,但不是很完美。 许多问题都与Layer Backed视图有关。

如果您没有图层支持或托管视图,则可以使用以下代码:

    NSData* data = [mainView dataWithPDFInsideRect:[mainView bounds]];
    NSImage *img = [[NSImage alloc] initWithData:data];

如果使用基于图层的视图:

直到10.8对我来说最好的方式是

        NSSize mySize = mapImage.bounds.size;
        NSSize imgSize = NSMakeSize( mySize.width, mySize.height );
        NSBitmapImageRep *bir = [mapImage bitmapImageRepForCachingDisplayInRect:[mapImage bounds]];
        [bir setSize:imgSize];
        [mapImage cacheDisplayInRect:[mapImage bounds] toBitmapImageRep:bir];
        caheImg = [[NSImage alloc]initWithSize:imgSize];
        [caheImg addRepresentation:bir];

但是在10.8 bitmapImageRepForCachingDisplayInRect停止了使用Layer Backed视图。

可以选择制作屏幕截图并剪切视图:

+ (NSImage*) screenCacheImageForView:(NSView*)aView
{
    NSRect originRect = [aView convertRect:[aView bounds] toView:[[aView window] contentView]];

    NSRect rect = originRect;
    rect.origin.y = 0;
    rect.origin.x += [aView window].frame.origin.x;
    rect.origin.y += [[aView window] screen].frame.size.height - [aView window].frame.origin.y - [aView window].frame.size.height;
    rect.origin.y += [aView window].frame.size.height - originRect.origin.y - originRect.size.height;

    CGImageRef cgimg = CGWindowListCreateImage(rect,
                                           kCGWindowListOptionIncludingWindow,
                                           (CGWindowID)[[aView window] windowNumber],
                                           kCGWindowImageDefault);
    return [[NSImage alloc] initWithCGImage:cgimg size:[aView bounds].size];
}

答案 1 :(得分:2)

我在我的应用中使用此代码,效果很好。

但是,如果我将应用程序拖到辅助监视器上,则会抛出屏幕截图,并且我会捕获错误的矩形。

以下代码修复了这个问题(我还从计算中删除了一些冗余数学,其中一个字段被减去然后添加)以防将来有人遇到此问题:

NSRect originRect = [aView convertRect:[aView bounds] toView:[[aView window] contentView]];

NSArray *screens = [NSScreen screens];
NSScreen *primaryScreen = [screens objectAtIndex:0];

NSRect rect = originRect;
rect.origin.y = 0;
rect.origin.x += [aView window].frame.origin.x;
rect.origin.y = primaryScreen.frame.size.height - [aView window].frame.origin.y - originRect.origin.y - originRect.size.height;

答案 2 :(得分:2)

@Remizorr的回答在ObjectiveC中起作用,就像在解释中一样 macOS High Sierra 10.13.4。 - Xcode 9.2。

它也适用于layerBacked视图(wantsLayer = true)。

这是更新的Swift版本:

extension NSView {

func snapshotImage() -> NSImage? {

    guard let window = window,
        let screen = window.screen,
        let contentView = window.contentView else { return nil }

    let originRect = self.convert(self.bounds, to:contentView)
    var rect = originRect
    rect.origin.x += window.frame.origin.x
    rect.origin.y = 0
    rect.origin.y += screen.frame.size.height - window.frame.origin.y - window.frame.size.height
    rect.origin.y += window.frame.size.height - originRect.origin.y - originRect.size.height
    guard window.windowNumber > 0 else { return nil }
    guard let cgImage = CGWindowListCreateImage(rect, .optionIncludingWindow, CGWindowID(window.windowNumber), CGWindowImageOption.bestResolution) else { return nil }

    return NSImage(cgImage: cgImage, size: self.bounds.size)
}

}

注意:即使对于WKWebView也是如此,它确实拍摄了WKWebView视频播放的快照(WKWebViews拍摄的快照没有);)。

答案 3 :(得分:-1)

很棒的Swifty解决方案

我想知道当Webview仅显示页面的一部分时如何为整个页面拍摄快照吗?下面的屏幕快照是使用提供的代码解决方案创建的。

enter image description here