Swift开发-截屏指定区域

#方法 1: 使用 UIGraphicsImageRenderer

swift 复制代码
func captureScreenArea(rect: CGRect) -> UIImage? {
    // 获取主窗口
    guard let window = UIApplication.shared.windows.first else { return nil }
    
    // 创建渲染器(自动处理 Retina 缩放)
    let renderer = UIGraphicsImageRenderer(bounds: rect)
    
    return renderer.image { context in
        // 将指定区域绘制到上下文
        window.drawHierarchy(in: window.bounds, afterScreenUpdates: false)
    }
}

// 使用示例
let captureRect = CGRect(x: 100, y: 200, width: 300, height: 200)
if let screenshot = captureScreenArea(rect: captureRect) {
    UIImageWriteToSavedPhotosAlbum(screenshot, nil, nil, nil) // 保存到相册
}

#方法 2: 使用 drawHierarchy

swift 复制代码
func captureViewArea(view: UIView, rect: CGRect) -> UIImage? {
    // 创建临时绘图上下文
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
    
    defer { UIGraphicsEndImageContext() } // 确保上下文关闭
    
    // 转换坐标系(视图坐标系 → 图像坐标系)
    let drawingRect = CGRect(
        x: -rect.origin.x,
        y: -rect.origin.y,
        width: view.bounds.width,
        height: view.bounds.height
    )
    
    // 渲染指定区域
    let success = view.drawHierarchy(in: drawingRect, afterScreenUpdates: false)
    
    guard success, let image = UIGraphicsGetImageFromCurrentImageContext() else {
        return nil
    }
    
    // 裁剪到目标区域
    guard let cgImage = image.cgImage?.cropping(to: CGRect(
        origin: .zero,
        size: rect.size
    )) else { return nil }
    
    return UIImage(cgImage: cgImage)
}

// 使用示例(截取某个子视图的区域)
let targetView = UIView(frame: CGRect(x: 50, y: 100, width: 200, height: 150))
if let screenshot = captureViewArea(view: targetView, rect: CGRect(x: 20, y: 30, width: 100, height: 80)) {
    // 使用截图...
}

#方法 3: 使用 CALayer 渲染(底层方法)

swift 复制代码
func captureLayerArea(layer: CALayer, rect: CGRect) -> UIImage? {
    // 创建位图上下文
    UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
    
    defer { UIGraphicsEndImageContext() }
    
    guard let context = UIGraphicsGetCurrentContext() else { return nil }
    
    // 调整上下文坐标系
    context.translateBy(x: -rect.origin.x, y: -rect.origin.y)
    
    // 渲染图层内容
    layer.render(in: context)
    
    return UIGraphicsGetImageFromCurrentImageContext()
}

// 使用示例(截取特定图层的区域)
let targetLayer = CALayer()
targetLayer.frame = CGRect(x: 0, y: 0, width: 400, height: 300)
if let screenshot = captureLayerArea(layer: targetLayer, rect: CGRect(x: 50, y: 50, width: 200, height: 200)) {
    // 处理截图...
}
方法 优点 缺点 适用场景
UIGraphicsImageRenderer 自动处理缩放,代码简洁 支持 iOS 10+ iOS 10+
drawHierarchy 兼容旧系统,支持实时渲染 需要手动处理坐标系 需要兼容 iOS 7+ 的项目
CALayer 渲染 底层控制,性能最优 无法捕获 OpenGL/Vulkan 内容 游戏或高性能渲染

#扩展功能实现

1. 带安全区域的截图

swift 复制代码
func safeAreaScreenshot() -> UIImage? {
    guard let window = UIApplication.shared.windows.first else { return nil }
    
    let safeArea = window.safeAreaInsets
    let captureRect = CGRect(
        x: safeArea.left,
        y: safeArea.top,
        width: window.bounds.width - safeArea.left - safeArea.right,
        height: window.bounds.height - safeArea.top - safeArea.bottom
    )
    
    return captureScreenArea(rect: captureRect)
}

2. 延时截图(解决渲染未完成问题)

less 复制代码
func delayedCapture(rect: CGRect, delay: TimeInterval, completion: @escaping (UIImage?) -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
        let screenshot = self.captureScreenArea(rect: rect)
        completion(screenshot)
    }
}

// 使用示例
delayedCapture(rect: CGRect(x: 0, y: 0, width: 200, height: 200), delay: 0.3) { image in
    guard let image = image else { return }
    // 处理截图...
}

3. 拼接多个区域

swift 复制代码
func combineScreenshots(rects: [CGRect]) -> UIImage? {
    guard !rects.isEmpty else { return nil }
    
    // 计算总区域
    let totalRect = rects.reduce(CGRect.null) { $0.union($1) }
    
    let renderer = UIGraphicsImageRenderer(bounds: totalRect)
    return renderer.image { context in
        for rect in rects {
            if let image = captureScreenArea(rect: rect) {
                image.draw(in: rect)
            }
        }
    }
}
相关推荐
吃饺子不吃馅33 分钟前
⚡️ Zustand 撤销重做利器:Zundo 实现原理深度解析
前端·javascript·github
幼儿园技术家38 分钟前
网站在苹果 Safari 进行适配遇到的问题
前端
IT_陈寒43 分钟前
7个鲜为人知的JavaScript性能优化技巧,让你的网页加载速度提升50%
前端·人工智能·后端
不坑老师1 小时前
不坑盒子的插入网页功能是完全免费的!
前端·html
Wang's Blog1 小时前
前端FAQ: 描述⼀下你最近使⽤过的前端框架,并解释为何选择它们?
前端·vue.js·faq
wgego1 小时前
做题笔记BUU (XSS-Lab)(1-14)
前端·笔记·xss
dllxhcjla1 小时前
css第二天
java·前端·css
远航_1 小时前
10 个被严重低估的 JS 特性,直接少写 500 行代码
前端·javascript
起这个名字1 小时前
感觉这篇 DeepSeek 给出的微前端实践很牛!轻喷!
前端
小高0071 小时前
当前端面临百万级 API 请求:从"修 CSS 的"到架构师的进化之路
前端·javascript·面试