【问题标题】:WKWebView CALayer to image exports blank imageWKWebView CALayer 到图像导出空白图像
【发布时间】:2017-06-16 20:37:13
【问题描述】:

我正在尝试截取网页截图,但图像始终为空白(白色)。

我正在使用此代码将CALayer 转换为Data(taken from here)

extension CALayer {

/// Get `Data` representation of the layer.
///
/// - Parameters:
///   - fileType: The format of file. Defaults to PNG.
///   - properties: A dictionary that contains key-value pairs specifying image properties.
///
/// - Returns: `Data` for image.

func data(using fileType: NSBitmapImageFileType = .PNG, properties: [String : Any] = [:]) -> Data {
    let width = Int(bounds.width * self.contentsScale)
    let height = Int(bounds.height * self.contentsScale)
    let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)!
    imageRepresentation.size = bounds.size

    let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!

    render(in: context.cgContext)

    return imageRepresentation.representation(using: fileType, properties: properties)!
}

}

然后将数据写入文件为.png

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) 
{
    let d = web.layer?.data() as NSData?  //web is the instance of WKWebView
    d!.write(toFile: "/Users/mac/Desktop/web.png", atomically: true)
}

但我得到的是一个空白(白色)的 png,而不是我所期望的

1)。我做错了什么?

2)。有没有其他可能的方法来获得图像表示 网页(使用swift)?

谢谢!

【问题讨论】:

    标签: swift macos cocoa wkwebview


    【解决方案1】:

    最新更新:

    现在你可以像WebView一样截图WKWebView

    Apple added new method 适用于 iOS 和 macOS,

    func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, 
    completionHandler: @escaping (NSImage?, Error?) -> Void)
    

    但它仍处于测试阶段。


    你不能截图WKWebView。它总是返回一个空白图像。即使您尝试将WKWebView 包含在另一个NSView 中并截屏,它也会为您提供空白图像来代替WKWebView

    您应该使用WebView 而不是WKWebView 来达到您的目的。检查这个question

    如果您可以使用私有框架(苹果不允许您的应用在其商店中),请查看此GitHub。它是用 Obj-C 编写的。我不知道 Obj-C,所以我无法解释该代码中发生了什么。但它声称可以完成这项工作。

    您最好的方法是使用WebView 并在WebView 上使用您提到的扩展名data()

    只是一个问题:为什么不使用 phantomJS?

    附言。这么晚才回复很抱歉。我没有看到你的电子邮件。

    【讨论】:

    • 谢谢!我看到了这个问题,但我从未见过那个 github repo,但遗憾的是我也不知道 objc。
    【解决方案2】:

    更新:Swift 5 添加到先前版本。

    我不想在输出中使用控件,所以我将一个键序列绑定到它(本地键监视器):

    case [NSEvent.ModifierFlags.option, NSEvent.ModifierFlags.command]:
        guard let window = NSApp.keyWindow, let wvc = window.contentViewController as? WebViewController else {
            NSSound(named: "Sosumi")?.play()
            return true
        }
        wvc.snapshot(self)
        return true
    

    并在沙盒环境中工作。我们在默认值中保留了一堆用户设置,例如他们希望在哪里捕获快照(~/Desktop),所以我们第一次询问/验证、缓存它,随后调用的应用程序委托将恢复沙盒书签.

    var webImageView = NSImageView.init()
    var player: AVAudioPlayer?
    
    @IBAction func snapshot(_ sender: Any) {
        webView.takeSnapshot(with: nil) {image, error in
            if let image = image {
                self.webImageView.image = image
            } else {
                print("Failed taking snapshot: \(error?.localizedDescription ?? "--")")
                self.webImageView.image = nil
            }
        }
        guard let image = webImageView.image else { return }
        guard let tiffData = image.tiffRepresentation else { NSSound(named: "Sosumi")?.play(); return }
    
        //  1st around authenticate and cache sandbox data if needed
        if appDelegate.isSandboxed(), appDelegate.desktopData == nil {
            let openPanel = NSOpenPanel()
            openPanel.message = "Authorize access to Desktop"
            openPanel.prompt = "Authorize"
            openPanel.canChooseFiles = false
            openPanel.canChooseDirectories = true
            openPanel.canCreateDirectories = false
            openPanel.directoryURL = appDelegate.getDesktopDirectory()
            openPanel.begin() { (result) -> Void in
                if (result == NSApplication.ModalResponse.OK) {
                    let desktop = openPanel.url!
                    _ = self.appDelegate.storeBookmark(url: desktop, options: self.appDelegate.rwOptions)
                    self.appDelegate.desktopData = self.appDelegate.bookmarks[desktop]
                    UserSettings.SnapshotsURL.value = desktop.absoluteString
                }
            }
        }
    
        //  Form a filename: ~/"<app's name> View Shot <timestamp>"
        let dateFMT = DateFormatter()
        dateFMT.dateFormat = "yyyy-dd-MM"
        let timeFMT = DateFormatter()
        timeFMT.dateFormat = "h.mm.ss a"
        let now = Date()
    
        let path = URL.init(fileURLWithPath: UserSettings.SnapshotsURL.value).appendingPathComponent(
            String(format: "%@ View Shot %@ at %@.png", appDelegate.appName, dateFMT.string(from: now), timeFMT.string(from: now)))
    
        let bitmapImageRep = NSBitmapImageRep(data: tiffData)
    
        //  With sandbox clearance to the desktop...
        do
        {
            try bitmapImageRep?.representation(using: .png, properties: [:])?.write(to: path)
    
            // https://developer.apple.com/library/archive/qa/qa1913/_index.html
            if let asset = NSDataAsset(name:"Grab") {
    
                do {
                    // Use NSDataAsset's data property to access the audio file stored in Sound.
                     player = try AVAudioPlayer(data:asset.data, fileTypeHint:"caf")
                    // Play the above sound file.
                    player?.play()
                } catch {
                    Swift.print("no sound for you")
                }
            }
        } catch let error {
            NSApp.presentError(error)
            NSSound(named: "Sosumi")?.play()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多