2016-09-02 9 views
6

Swiftでボタンをプログラムした後、ユーザーが自分のアプリに行ってアプリのスクリーンショットを撮ってもらいたい。私はUIGraphicsGetImageFromCurrentImageContext()がスクリーンショットを取ることを知っていますが、私はスクリーン全体の画像を望んでいません。私は矩形をポップアップ(作物ツールのようなもの)したいと思うし、ユーザーは、画面の特定の部分のみのスクリーンショットを取るために四角形をドラッグしてサイズ変更することができます。矩形をWKWebViewに移動して、Webビューの画像を切り抜きたい。UIViewの一部のスクリーンショットを取る方法は?

答えて

16

標準スナップショットのテクニックはdrawViewHierarchyInRectです。画像の一部を取得するには、CGImageCreateWithImageInRectを使用します。スウィフト2でこのように

、:スウィフト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, 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) 
    } 

} 

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

完璧なソリューション。 SOには他のものがありますが、画面全体をキャプチャします。これは両方のソリューションです。 – 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()

を尋ねることによってしますか

これは荒いと思いますが、糸の安全性などをさらに検討する必要があるかもしれませんが....

関連する問題