Swiftでプログラムでボタンを押した後、ユーザーが自分のアプリにアクセスしてアプリのスクリーンショットを撮ってほしい。 UIGraphicsGetImageFromCurrentImageContext()
がスクリーンショットを撮ることは知っていますが、画面全体の写真は必要ありません。長方形をポップアップさせたいのですが(切り抜きツールのようなものです)、ユーザーは長方形をドラッグしてサイズを変更し、画面の特定の部分のみのスクリーンショットを撮ることができます。長方形がWKWebView
を越えて、Webビューの写真を切り抜いてほしい。
標準のスナップショット手法は drawHierarchy(in:afterScreenUpdates:)
であり、それを画像コンテキストに描画します。 iOS 10以降では、 UIGraphicsImageRenderer
:を使用できます。
_extension UIView {
/// Create image snapshot of view.
///
/// - Parameters:
/// - rect: The coordinates (in the view's own coordinate space) to be captured. If omitted, the entire `bounds` will be captured.
/// - afterScreenUpdates: A Boolean value that indicates whether the snapshot should be rendered after recent changes have been incorporated. Specify the value false if you want to render a snapshot in the view hierarchy’s current state, which might not include recent changes. Defaults to `true`.
///
/// - Returns: The `UIImage` snapshot.
func snapshot(of rect: CGRect? = nil, afterScreenUpdates: Bool = true) -> UIImage {
return UIGraphicsImageRenderer(bounds: rect ?? bounds).image { _ in
drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates)
}
}
}
_
そして、あなたはそのようにそれを使うでしょう:
_let image = webView.snapshot(of: rect)
_
IOS 10より前は、画像の一部を取得するため、CGImage
メソッド cropping(to:)
を使用できます。例えば。:
_extension UIView {
/// Create snapshot
///
/// - Parameters:
/// - rect: The coordinates (in the view's own coordinate space) to be captured. If omitted, the entire `bounds` will be captured.
/// - afterScreenUpdates: A Boolean value that indicates whether the snapshot should be rendered after recent changes have been incorporated. Specify the value false if you want to render a snapshot in the view hierarchy’s current state, which might not include recent changes. Defaults to `true`.
///
/// - Returns: Returns `UIImage` of the specified portion of the view.
func snapshot(of rect: CGRect? = nil, afterScreenUpdates: Bool = true) -> UIImage? {
// snapshot entire view
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates)
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
guard let cgImage = image.cgImage?.cropping(to: rect * image.scale) else { return nil }
return UIImage(cgImage: cgImage, scale: image.scale, orientation: .up)
}
}
_
この少し便利な演算子を使用します:
_extension CGRect {
static func * (lhs: CGRect, rhs: CGFloat) -> CGRect {
return CGRect(x: lhs.minX * rhs, y: lhs.minY * rhs, width: lhs.width * rhs, height: lhs.height * rhs)
}
}
_
そしてそれを使用するには、次のことができます。
_if let image = webView.snapshot(of: rect) {
// do something with `image` here
}
_
Swift 2レンディションについては、 この回答の以前のリビジョン を参照してください。
これは以前に尋ねられた質問です 網膜ディスプレイの品質を損なうことなくUIViewをUIImageにキャプチャする方法 しかしSwift(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()
を要求することができます。
これは大まかなことであり、おそらくスレッドセーフなどをさらに検討する必要があることを覚えておいてください。