菜鸟教程小白 发表于 2022-12-12 14:40:06

ios - ARKit - 如何在另一个 SCNNode 中包含 SCNText(对话泡泡)


                                            <p><p>我正在尝试在 ARKit 的对话泡泡中创建一个带有简单文本的报价生成器。</p>

<p>我可以用文本显示对话泡泡,但文本总是从中间开始溢出到对话泡泡之外。</p>

<p>任何让它在对话泡泡左上角对齐并在对话泡泡内环绕的帮助将不胜感激。</p>

<p><strong>结果</strong></p>

<p> <a href="/image/mb9GN.jpg" rel="noreferrer noopener nofollow"><img src="/image/mb9GN.jpg" alt="enter image description here"/></a> </p>

<p><strong>类</strong></p>

<pre><code>class SpeechBubbleNode: SCNNode {
    private let textNode = TextNode()

    var string: String? {
      didSet {
            textNode.string = string
      }
    }

    override init() {
      super.init()

      // Speech Bubble
      let plane = SCNPlane(width: 200.0, height: 100.0)
      plane.cornerRadius = 4.0
      plane.firstMaterial?.isDoubleSided = true
      geometry = plane

      // Text Node
      textNode.position = SCNVector3(position.x, position.y, position.z + 1.0)
//      textNode.position = convertPosition(SCNVector3(0.0, 0.0, 1.0), to: textNode)
//      textNode.position = SCNVector3(0.0, 0.0, position.z + 1.0)
      addChildNode(textNode)
    }

    required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
    }
}

class TextNode: SCNNode {
    private let textGeometry = SCNText()

    var string: String? {
      didSet {
            updateTextContainerFrame()
            textGeometry.string = string
      }
    }

    override init() {
      super.init()

      textGeometry.truncationMode = CATextLayerTruncationMode.middle.rawValue
      textGeometry.isWrapped = true
      textGeometry.alignmentMode = CATextLayerAlignmentMode.left.rawValue

      let blackMaterial = SCNMaterial()
      blackMaterial.diffuse.contents = UIColor.black
      blackMaterial.locksAmbientWithDiffuse = true
      textGeometry.materials =

      geometry = textGeometry
    }

    required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
    }

    private func updateTextContainerFrame() {
      let (min, max) = boundingBox
      let width = CGFloat(max.x - min.x)
      let height = CGFloat(max.y - min.y)
      print(&#34;width :&#34;,max.x - min.x,&#34;height :&#34;,max.y - min.y,&#34;depth :&#34;,max.z - min.z)
      textGeometry.containerFrame = CGRect(x: 0.0, y: 0.0, width: width, height: height)
//      textGeometry.containerFrame = CGRect(origin: .zero, size: CGSize(width: 1.0, height: 1.0))
    }
}
</code></pre>

<p><strong>实现</strong></p>

<pre><code>private func makeSpeechBubbleNode(forBobbleheadNode bobbleheadNode: BobbleheadNode) {
    let node = SpeechBubbleNode()
    node.position = sceneView.scene.rootNode.convertPosition(bobbleheadNode.position, to: node)
    node.scale = SCNVector3(0.002, 0.002, 0.002)

    sceneView.scene.rootNode.addChildNode(speechBubbleNode)
    self.speechBubbleNode = speechBubbleNode

    speechBubbleNode.string = &#34;Some random string that could be long and should wrap within speech bubble&#34;
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我遇到了同样的问题,最后我解决了如下问题:</p>

<ul>
<li><p>创建一个 SCNText 并将其作为几何图形添加到 SCNNode:</p>

<pre><code>let string = &#34;Coverin text with a plane :)&#34;
let text = SCNText(string: string, extrusionDepth: 0.1)
text.font = UIFont.systemFont(ofSize: 1)
text.flatness = 0.005
let textNode = SCNNode(geometry: text)
let fontScale: Float = 0.01
textNode.scale = SCNVector3(fontScale, fontScale, fontScale)
</code></pre> </li>
<li><p> <a href="https://stackoverflow.com/a/44829260/1724845" rel="noreferrer noopener nofollow">Coordinate the text pivot form left bottom to center</a> :</p>

<pre><code>let (min, max) = (text.boundingBox.min, text.boundingBox.max)
let dx = min.x + 0.5 * (max.x - min.x)
let dy = min.y + 0.5 * (max.y - min.y)
let dz = min.z + 0.5 * (max.z - min.z)
textNode.pivot = SCNMatrix4MakeTranslation(dx, dy, dz)
</code></pre> </li>
<li><p>创建一个 PlaneNode 并将文本节点添加为 PlaneNode 的子节点:</p>

<pre><code>let width = (max.x - min.x) * fontScale
let height = (max.y - min.y) * fontScale
let plane = SCNPlane(width: CGFloat(width), height: CGFloat(height))
let planeNode = SCNNode(geometry: plane)
planeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
planeNode.geometry?.firstMaterial?.isDoubleSided = true
planeNode.position = textNode.position
textNode.eulerAngles = planeNode.eulerAngles
planeNode.addChildNode(textNode)
</code></pre> </li>
<li><p>最后将 PlaneNode 添加到 sceneView:</p>

<pre><code>sceneView.scene.rootNode.addChildNode(planeNode)
</code></pre> </li>
</ul>

<p>这就是结果:</p>

<p> <a href="/image/O1HYK.jpg" rel="noreferrer noopener nofollow"><img src="/image/O1HYK.jpg" alt="enter image description here"/></a> </p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - ARKit - 如何在另一个 SCNNode 中包含 SCNText(对话泡泡),我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/50731775/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/50731775/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - ARKit - 如何在另一个 SCNNode 中包含 SCNText(对话泡泡)