Swift UI 导出画布内容

2024-05-23

我有一个画布,用户可以在上面画东西。我想导出用户在画布上绘制的任何内容,并且我正在使用以下扩展从视图中获取图像

extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view

        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear

        let renderer = UIGraphicsImageRenderer(size: targetSize)

        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

但不幸的是,这个扩展适用于任何简单视图上的按钮。每当我将它用于画布时,它都会给我一个空白图像,看起来它没有获取画布的内容。

是否可以导出我的画布内容?

是因为我用笔画画画布吗?

这就是我使用画布的方式:

    @State private var currentLine = Line(color: .red)
    @State private var drawedLines = [Line]()
    @State private var selectedColor: Color = .red
    @State private var selectedSize = 1.0
    private var colors:[Color] = [.red, .green, .blue, .black, .orange, .yellow, .brown, .pink, .purple, .indigo, .cyan, .mint]

    var canvasPallete: some View {
        return Canvas { context, size in
            for line in drawedLines {
                var path = Path()
                path.addLines(line.points)
                context.stroke(path, with: .color(line.color), lineWidth: line.size)
            }

        }.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
            .onChanged({ value in
                let point = value.location
                currentLine.points.append(point)
                currentLine.color = selectedColor
                currentLine.size = selectedSize
                drawedLines.append(currentLine)
            })
            .onEnded({ value in
                currentLine = Line(color: selectedColor)
             })
        )
    }

    var body: some View {
        VStack {
            canvasPallete
                .frame(width: 300, height: 300)
            Divider()
            HStack(alignment: .bottom ) {
                VStack{
                    Button {
                        print("Will save draw image")
                        let image = canvasPallete.snapshot()
                        
                        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
                    } label: {
                        Text("Save")
                    }
                    .padding([.bottom], 25)

                    Button {
                        drawedLines.removeAll()
                    } label: {
                        Image(systemName: "trash.circle.fill")
                            .font(.system(size: 40))
                            .foregroundColor(.red)
                    }.frame(width: 70, height: 50, alignment: .center)
                }
                VStack(alignment: .leading) {
                    Text("Colors:")
                    ScrollView(.horizontal, showsIndicators: false) {
                        HStack(spacing: 4) {
                            ForEach(colors, id:\.self){color in
                                ColoredCircleButton(color: color, selected: color == selectedColor) {
                                    selectedColor = color
                                }
                            }

                        }
                        .padding(.all, 5)

                    }
                    Text("Size:")
                    Slider(value: $selectedSize, in: 0.2...8)
                        .padding([.leading,.trailing], 20)
                        .tint(selectedColor)
                }
                .padding([.bottom], 10)

            }


        }.frame(minWidth: 400, minHeight: 400)
    }
}


    struct ColoredCircleButton: View {
        let color: Color
        var selected = false
        let onTap: (() -> Void)
    
        var body: some View {
            Circle()
                .frame(width: 25, height: 25)
                .foregroundColor(color)
                .overlay(content: {
                    if selected {
                        Circle().stroke(.gray, lineWidth: 3)
                    }
                })
                .onTapGesture {
                    onTap()
                }
        }
    }

这很好用!

您遇到的问题是在您的示例代码中,canvasPallete没有获得框架修改器snapshot()被要求这样做。所以它的渲染尺寸不是你想要的,可能是 (0,0)。

如果您更改快照行,它将起作用:

let image = canvasPallete
    .frame(width: 300, height: 300)
    .snapshot()

还有一件事!在 iOS 16 中,有新的 API 用于将视图渲染为图像。因此,对于 iOS 16 及更高版本,您可以跳过 View 扩展并编写:

let renderer = ImageRenderer(content: canvasPallete)
if let image = renderer.uiImage {
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift UI 导出画布内容 的相关文章

  • 在 Swift 中解码 JSON Web 令牌

    尝试在 Swift 中解码 JWT 有效负载 但遇到了很大的困难 static func decodePayload tokenstr String splitting JWT to extract payload let arr spli
  • 将英语日期转换为法语、nsdate、本地化的最佳方法

    我的财产dob of Patient对象是String目前正在存储12 Jan 2017我想将其转换为法语语言环境 例如12 Janv 2017 以下是我的步骤 转换12 Jan 2017 into 1954 09 07 04 00 00
  • Swift:覆盖子类内的类型别名

    所以我正在考虑在我的项目中使用自定义模式 但我无法让它发挥作用 主要思想是改变typealias在每个子类上访问子类特定的接口 protocol InstanceInterface class typealias Interface var
  • iOS 应用程序在 segue 处崩溃(断点发生在 func prepareForSegue 处)

    更新 我发现 仅通过阅读代码来调试是非常困难的 特别是在这样的情况下 https www dropbox com s ty3clsvgednzevj LoaferMap 20for 20iPhone 20copy 202 zip dl 0
  • 与 UIActivityViewController 共享 PDF 文件

    我正在尝试使用共享 PDF 文件UIActivityViewController但是当我按下按钮时 我没有共享文件的选项 我怎样才能显示这些选项 https i stack imgur com ywDQw jpg https i stack
  • Swift 类型推断和类型检查问题

    我不是在寻找如何正确执行此操作的答案 而是在寻找为什么会发生这种情况的答案 这是代码 func isInt param AnyObject if let value param as Int print value else print N
  • 如何从 Swift 调用 Objective-C 代码?

    在 Swift 中 如何调用 Objective C 代码 Apple 提到它们可以在一个应用程序中共存 但这是否意味着在技术上可以重用 Objective C 中创建的旧类 同时在 Swift 中构建新类 在 Swift 中使用 Obje
  • Swift:将字符串转换为十六进制颜色代码

    我已经从数据库生成了用户 ID 格式类似于 XzSYoKJaqKYREkdB2dgwt0fLOPP2 我想用它来创建 UIColor 我找到了几个解决方案 https github com yeahdongcn UIColor Hex Sw
  • 返回 Self 的协议函数

    我有一个返回对象副本的协议 P protocol P func copy gt Self 和一个实现 P 的 C 类 class C P func copy gt Self return C 但是 我是否将返回值设置为Self我收到以下错误
  • 如何从 GCD (DispatchQueue) 转换为 Swift async/await?

    我正在关注斯坦福大学的 CS193p 开发 iOS 应用程序在线课程 它使用 Grand Central Dispatch GCD API 来演示多线程 但他们指出 自 WWDC 2021 起 GCD 已大部分被 Swift 新的内置异步
  • 对于 Swift 中的计算器

    只是要警告你 我是 Swift 的新手 我仍在适应它的工作原理 我一直在尝试在课堂上完成这个计算器项目 问题是 我需要练习简化代码 现在 当按下数字按钮时 我将其保存在这样的数组中 IBAction func buttonPressed s
  • 在 Android 上使用 opus 剪辑从 IOS 发送的声音

    我正在 IOS 中从 audioUnit 录制音频 用 opus 编码字节并通过 UDP 将其发送到 android 端 问题是播放的声音有点削波 我还通过将原始数据从 IOS 发送到 Android 来测试声音 效果非常完美 我的 Aud
  • 从数组中获取随机字符串[重复]

    这个问题在这里已经有答案了 我试图从数组 firstArray 中获取随机字符串并将其打印在 UILabel label 中 我似乎无法弄清楚并且出现错误 感谢您的帮助 我尝试搜索但找不到任何最新的教程 方法 import UIKit cl
  • 带闭包的默认属性值使编译器重新编译所有文件

    This source https developer apple com library content documentation Swift Conceptual Swift Programming Language Initiali
  • Swift Generics 在使用继承时不会实例化泛型

    我有课Alpha and Berry class Alpha class Berry Alpha 我有一个使用继承及其泛型的函数 func myFunc
  • 在没有预览窗口的情况下使用 AVCaptureVideoDataOutputSampleBufferDelegate

    我正在开发一个基于 Swift 的 macOS 应用程序 我需要捕获视频输入 但不将其显示在屏幕上 而不是显示视频 我想将缓冲的数据发送到其他地方进行处理 并最终显示它在 a 中的一个物体上SceneKit scene 我有一个Camera
  • 如何使用 Swift 使用 TouchID?

    Apple 为 iOS 8 的 TouchID 实现提供的文档采用 Objective C 语言 有 Swift 版本吗 Objective C IBAction touchIDAvailable UIButton touchIDAvail
  • 减少 CoreData 的调试输出?

    我正在开发一个使用 CoreData 的 iOS macOS 项目 它工作正常 但它会向控制台输出大量调试信息 这使得控制台无法使用 因为我的打印语句隐藏在所有与 CoreData 相关的内容中 我有一个非常简单的 CoreData 设置
  • 作为!与 Swift 中 Xcode 6.3 中的 as 运算符对比

    Xcode 6 3 使 Swift 发生了很大变化 我必须更换每个应用程序中的数十个位置as gt as 为什么 现在有什么规则 在 Swift 1 2 之前 as运算符可用于执行两种不同类型的转换 具体取决于要转换的表达式的类型及其要转换
  • 如何让按钮闪烁?

    我试图在扫描正确时将按钮的颜色 只是闪烁 闪烁 更改为绿色 在出现问题时将按钮的颜色更改为红色 我可以用这样的视图来做到这一点 func flashBG UIView animateWithDuration 0 7 animations s

随机推荐