我有一个用SceneKit构建的交互式地球仪.地球是一个SCN node ,代表陆地的点也是SCN node ,是地球的子 node .我想添加一个自定义视图作为地球的一个子对象的几何图形.我知道如何添加一个球形几何体的 node ,改变它的 colored颜色 等等.我不知道如何使用一个自定义视图(swift ui)的几何体的 node .

 let lowerCircle = SCNSphere(radius: dotRadius * 5)
 lowerCircle.firstMaterial?.diffuse.contents = GenericColor(cgColor: UIColor.white.cgColor)
 lowerCircle.firstMaterial?.lightingModel = SCNMaterial.LightingModel.constant

 let dotNode = SCNNode(geometry: lowerCircle)
                    
 dotNode.name = "NewYorkDot"
 dotNode.position = textureMap[i].position
 positions.append(dotNode.position)
 dotNodes.append(dotNode)

推荐答案

要使用自定义SwiftUI视图作为SceneKit中SCNNode的几何体,可以从将SwiftUI视图渲染为UIImage开始.这可以通过创建视图的快照来完成.

Once you have the UIImage, you can apply it as a texture to the SCNMaterial of your SCNNode.
See for instance "Updating SCNMaterial texture in SceneKit" from Benoit Layer.

最后,创建一个geometry(例如,SCNPlane),并将具有自定义纹理的material 应用于此几何体.

这一过程将是:

[ SwiftUI View ]
    │
    ├─ Render to UIImage
    │
[ UIImage ]
    │
    ├─ Apply as Texture to Material
    │
[ SCNMaterial ]
    │
    ├─ Attach to SCNPlane or other geometry
    │
[ SCNNode ]

您的SwiftUI View to UIImage将是:

import SwiftUI

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

        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height)
        view?.backgroundColor = .clear

        let renderer = UIGraphicsImageRenderer(size: targetSize)
        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

然后应用自定义几何体:

import SceneKit
import SwiftUI

// Example SwiftUI View
struct CustomView: View {
    var body: some View {
        Text("Hello World")
            .frame(width: 100, height: 100)
            .background(Color.red)
    }
}

// Convert SwiftUI view to UIImage
let image = CustomView().snapshot()

// Create material with this image
let material = SCNMaterial()
material.diffuse.contents = image

// Create a geometry, e.g., SCNPlane
let plane = SCNPlane(width: 1.0, height: 1.0)
plane.materials = [material]

// Create a SCNNode with this geometry
let customNode = SCNNode(geometry: plane)

// Position and add the custom node as needed
customNode.position = SCNVector3(x: 0, y: 0, z: 0)
dotNode.addChildNode(customNode)

但是:SwiftUI视图呈现为静态图像,因此它们在SceneKit上下文中不是交互式的.


警告=== AttributeGraph: cycle detected through attribute 1517200 ===表示SwiftUI中存在循环依赖或与视图布局相关的问题.当视图的状态发生变化,导致SwiftUI不断重新计算视图的布局,从而导致无限循环时,就会发生这种情况.

所以试着简化SwiftUI视图:暂时用一个非常简单的视图(比如一个Text元素)替换SwiftUI视图,以确认是否是视图的复杂性导致了问题.

并确保您没有使用任何可能导致循环依赖的视图修改器,例如那些依赖于视图自身大小或布局的修改器.在将SwiftUI视图渲染为UIImage之前,为其设置明确的帧大小.这有助于防止与可能导致循环的大小计算相关的问题.

extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self.frame(width: 100, height: 100))
        let view = controller.view

        let targetSize = CGSize(width: 100, height: 100)
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear

        let renderer = UIGraphicsImageRenderer(size: targetSize)
        return renderer.image { _ in
            view?.drawHierarchy(in: CGRect(origin: .zero, size: targetSize), afterScreenUpdates: true)
        }
    }
}

确保在主线程上执行所有与UI相关的任务,包括将SwiftUI视图呈现为UIImage.

DispatchQueue.main.async {
    let image = CustomView().snapshot()

    // Create material with this image
    let material = SCNMaterial()
    material.diffuse.contents = image

    // Rest of the code to create and add SCNNode
    // 
}

Ios相关问答推荐

如何正确测试后台URLSessionDownloadTask?

SWIFT设备方向更新不正确

滚动时突出显示工具栏项目

在许多UIButton中对齐文本,即使SF Symbols(或其他图像)具有不同的宽度?

在SwiftUI中插入绘制重复形状

当S没有身体时该如何处理

IOS-获取本地化系统映像

在 React Native iOS 中加载多个 JS 包

在 Swift 中,对象如何被准确地从内存中移除?

Apple Metal iOS 为什么 GLKMatrix4MakeLookAt 来回摇摆

归档时命令 PhaseScriptExecution 失败,退出代码非零

如何为 XCTest、SwiftUI 预览等初始化带有 @MainActor 注释的 Swift 类

我无法使用 Swift 将文件上传到 firebase

react 在 android 上运行的本机应用程序,但在 iOS 上出现问题,详细信息在描述中共享

在使用 Github Actions 时,我面临权限被拒绝错误

无法结合 UIImageView 旋转动画和 tableView 部分重新加载

何时需要将应用程序源包含在测试目标中?

界面生成器 - 无法从路径加载设计对象(空)

如果已安装,则重定向到应用程序,否则重定向到 App Store

更改标签栏项目图像和文本 colored颜色 iOS