2016-09-02 84 views
6

我希望用戶在我的應用程序中繼續,並在Swift中以編程方式按下按鈕後截取應用程序。我知道UIGraphicsGetImageFromCurrentImageContext()需要截圖,但我不想要整個屏幕的圖片。我想要一個矩形彈出(有點像裁剪工具),用戶可以拖動和調整矩形的大小來截取屏幕的某個部分。我想讓這個矩形遍歷WKWebView並裁剪一張網頁視圖。如何截取部分UIView的截圖?

回答

16

標準快照技術是drawViewHierarchyInRect。要獲取圖像的一部分,可以使用CGImageCreateWithImageInRect

因此,斯威夫特2:

extension UIView { 

    /// Create snapshot 
    /// 
    /// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted), 
    ///     return snapshot of the whole view. 
    /// 
    /// - returns: Returns `UIImage` of the specified portion of the view. 

    func snapshot(of rect: CGRect? = nil) -> UIImage? { 
     // snapshot entire view 

     UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, 0) 
     drawViewHierarchyInRect(bounds, afterScreenUpdates: true) 
     let wholeImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     // if no `rect` provided, return image of whole view 

     guard let rect = rect, let image = wholeImage else { return wholeImage } 

     // otherwise, grab specified `rect` of image 

     let scale = image.scale 
     let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale) 
     guard let cgImage = CGImageCreateWithImageInRect(image.CGImage!, scaledRect) else { return nil } 
     return UIImage(CGImage: cgImage, scale: scale, orientation: .Up) 
    } 

} 

在斯威夫特3:

extension UIView { 

    /// Create snapshot 
    /// 
    /// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted), 
    ///     return snapshot of the whole view. 
    /// 
    /// - returns: Returns `UIImage` of the specified portion of the view. 

    func snapshot(of rect: CGRect? = nil) -> UIImage? { 
     // snapshot entire view 

     UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0) 
     drawHierarchy(in: bounds, afterScreenUpdates: true) 
     let wholeImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     // if no `rect` provided, return image of whole view 

     guard let image = wholeImage, let rect = rect else { return wholeImage } 

     // otherwise, grab specified `rect` of image 

     let scale = image.scale 
     let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale) 
     guard let cgImage = image.cgImage?.cropping(to: scaledRect) else { return nil } 
     return UIImage(cgImage: cgImage, scale: scale, orientation: .up) 
    } 

} 

,並使用它,你可以這樣做:

if let image = webView.snapshot(of: rect) { 
    // do something with `image` here 
} 
+1

偉大的工作一如既往羅布。謝謝。 – damirstuhec

+0

完美的解決方案。還有其他的,但他們捕捉整個屏幕。這是兩個解決方案。 – Septronic

3

這是How to capture UIView to UIImage without loss of quality on retina display(2.3)先前提出的問題,但在迅速擴大:

extension UIView { 

    class func image(view: UIView) -> UIImage? { 
     UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0) 
     guard let ctx = UIGraphicsGetCurrentContext() else { 
      return nil 
     } 
     view.layer.renderInContext(ctx) 
     let img = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return img 
    } 

    func image() -> UIImage? { 
     return UIView.image(self) 
    } 
} 

所以您可以得到一個視圖中的圖像與UIView.image(theView)或要求的觀點本身let viewImage = self.view.image()

不要忘記,這是粗糙的,可能需要進一步尋找線程安全等......