关于ios:如何截取WKWebview的整页截图?

How to capture a full page screenshot of WKWebview?

我可以通过调整UIWebViewUIScrollView的框架来捕获UIWebView的所有内容截图。但是,我无法通过相同的方法捕获 WKWebView 的所有内容屏幕截图。

我用于捕获UIWebView的方法如下:

  • webview.scrollView 的备份框架和超级视图
  • 创建一个新的容器视图作为 webview.scrollView 的超级视图
  • 调整新容器视图和 webview.scrollView 的框架。框架与 webview.scrollView.contentSize 相同
  • 通过 renderInContextdrawViewHierarchyInRect 绘制
  • 但是,此方法将捕获 WKWebView 的白色屏幕截图。它不起作用!

    我打印了所有级别的WKWebView,然后我发现一个UIView(WKContentView)的大小与contentView相同,你可以通过这个级别找到这个视图:

    • WKWebView

      • WK滚动视图

        • WKContentView(大小与 contentView 相同)

    我也曾尝试通过WKContentView进行捕捉,然后我发现只能捕捉到可见视图。

    无论如何,谁能告诉我如何截取WKWebView的整页内容截图?


    请参考这个答案

    iOS 11.0 及以上,Apple 提供了以下 API 来捕捉 WKWebView 的快照。

    1
    2
    @available(iOS 11.0, *)
        open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: @escaping (UIImage?, Error?) -> Swift.Void)


    Swift 3,Xcode 8

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    func takeScreenshot() -> UIImage? {
        let currentSize = webView.frame.size
        let currentOffset = webView.scrollView.contentOffset

        webView.frame.size = webView.scrollView.contentSize
        webView.scrollView.setContentOffset(CGPoint.zero, animated: false)

        let rect = CGRect(x: 0, y: 0, width: webView.bounds.size.width, height: webView.bounds.size.height)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
        webView.drawHierarchy(in: rect, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        webView.frame.size = currentSize
        webView.scrollView.setContentOffset(currentOffset, animated: false)

        return image
    }


    n


    Swift 3,Xcode 9:
    我创建了一个扩展来实现这一点。希望这对你有帮助。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    extension WKWebView{

         private func stageWebViewForScreenshot() {
            let _scrollView = self.scrollView
            let pageSize = _scrollView.contentSize;
            let currentOffset = _scrollView.contentOffset
            let horizontalLimit = CGFloat(ceil(pageSize.width/_scrollView.frame.size.width))
            let verticalLimit = CGFloat(ceil(pageSize.height/_scrollView.frame.size.height))

             for i in stride(from: 0, to: verticalLimit, by: 1.0) {
                for j in stride(from: 0, to: horizontalLimit, by: 1.0) {
                    _scrollView.scrollRectToVisible(CGRect(x: _scrollView.frame.size.width * j, y: _scrollView.frame.size.height * i, width: _scrollView.frame.size.width, height: _scrollView.frame.size.height), animated: true)
                     RunLoop.main.run(until: Date.init(timeIntervalSinceNow: 1.0))
                }
            }
            _scrollView.setContentOffset(currentOffset, animated: false)
        }

         func fullLengthScreenshot(_ completionBlock: ((UIImage) -> Void)?) {
            // First stage the web view so that all resources are downloaded.
             stageWebViewForScreenshot()

            let _scrollView = self.scrollView

            // Save the current bounds
            let tmp = self.bounds
            let tmpFrame = self.frame
             let currentOffset = _scrollView.contentOffset

            // Leave main thread alone for some time to let WKWebview render its contents / run its JS to load stuffs.
             mainDispatchAfter(2.0) {
                // Re evaluate the size of the webview
                let pageSize = _scrollView.contentSize
                 UIGraphicsBeginImageContext(pageSize)

                self.bounds = CGRect(x: self.bounds.origin.x, y: self.bounds.origin.y, width: pageSize.width, height: pageSize.height)
                self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: pageSize.width, height: pageSize.height)

                // Wait few seconds until the resources are loaded
                RunLoop.main.run(until: Date.init(timeIntervalSinceNow: 0.5))

                 self.layer.render(in: UIGraphicsGetCurrentContext()!)
                let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
                UIGraphicsEndImageContext()

                // reset Frame of view to origin
                self.bounds = tmp
                self.frame = tmpFrame
                _scrollView.setContentOffset(currentOffset, animated: false)

                 completionBlock?(image)
            }
        }
    }

    -xcode 10


    n


    更新:不知道为什么杰森会在整个网络上贴这个答案。它不能解决如何截取完整的 WKWebView 内容的问题......包括屏幕外的内容。

    试试这个:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    func snapshot() -> UIImage {
            UIGraphicsBeginImageContextWithOptions(self.webView.bounds.size, true, 0);
            self.webView.drawViewHierarchyInRect(self.webView.bounds, afterScreenUpdates: true);
            let snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            UIImageWriteToSavedPhotosAlbum(snapshotImage, nil, nil, nil)

            return snapshotImage
        }

    图像将自动保存到 iOS 相机胶卷中(通过 UIImageWriteToSavedPhotosAlbum())。