我希望用户在我的应用程序上按程序按钮后,能够截取应用程序的屏幕截图。我知道UIGraphicsGetImageFromCurrentImageContext()
可以截屏,但我不想要整个屏幕的图片。我想让一个矩形框弹出(有点像剪裁工具),用户可以拖动和调整矩形框的大小来截取屏幕的某一部分。我希望这个矩形框覆盖在一个WKWebView
上,并剪裁出WebView的图片。
我希望用户在我的应用程序上按程序按钮后,能够截取应用程序的屏幕截图。我知道UIGraphicsGetImageFromCurrentImageContext()
可以截屏,但我不想要整个屏幕的图片。我想让一个矩形框弹出(有点像剪裁工具),用户可以拖动和调整矩形框的大小来截取屏幕的某一部分。我希望这个矩形框覆盖在一个WKWebView
上,并剪裁出WebView的图片。
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()
来获取视图的图像。
请注意,这仅是初步版本,可能需要进一步考虑线程安全等问题。
已更新为Swift 5,并对代码进行了一些简化。
extension UIView {
var image: UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0.0)
guard let context = UIGraphicsGetCurrentContext() else {
return nil
}
layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}