【问题标题】:ARKit - How to contain SCNText within another SCNNode (speech bubble)ARKit - 如何在另一个 SCNNode 中包含 SCNText(讲话泡泡)
【发布时间】:2018-11-16 19:27:40
【问题描述】:

我正在尝试在 ARKit 的语音气泡中创建一个带有简单文本的报价生成器。

我可以用文字显示对话泡泡,但文字总是从中间开始,溢出对话泡泡之外。

如果能帮助它在对话气泡的左上角对齐并包裹在对话气泡内,我们将不胜感激。

结果

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 = [blackMaterial]

        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("width :",max.x - min.x,"height :",max.y - min.y,"depth :",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))
    }
}

实施

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 = "Some random string that could be long and should wrap within speech bubble"
}

【问题讨论】:

    标签: ios arkit word-wrap scnnode scntext


    【解决方案1】:

    如果您只需要文本后面的白框,我通过在渲染器函数中执行此操作来实现:

    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    
            let node = SCNNode()
    
            ............
    
            let testPlane = SCNPlane(width: someWidth, height: someHeight)
    
    
            let testScene = SKScene(size: CGSize(width: 900, height: 900))
            testScene.backgroundColor = UIColor.white
    
            let str = SKLabelNode(text: "This is just a test")
            str.color = UIColor.black
            str.fontColor = UIColor.black
            str.fontSize = 45.5
    
            str.position = CGPoint(x: stuff.size.width / 2,
                                     y: stuff.size.height / 2)
            testScene.addChild(str)
    
            testPlane.firstMaterial?.diffuse.contents = testScene
            testPlane.firstMaterial?.isDoubleSided = true
            testPlane.firstMaterial?.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)
    
            let testNode = SCNNode(geometry: testPlane)
    
    
            testNode.eulerAngles.x = -.pi / 2
            testNode.position = SCNVector3Make(0.0,0.0,0.0)
    
            node.addChildNode(testNode)
    
    
    }
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,最后我解决了如下:

      • 创建一个 SCNText 并将其作为几何图形添加到 SCNNode:

        let string = "Coverin text with a plane :)"
        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)
        
      • Coordinate the text pivot form left bottom to center:

        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)
        
      • 创建一个PlaneNode并将textNode添加为PlaneNode的childNode:

        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)
        
      • 最后将 PlaneNode 添加到场景视图中:

        sceneView.scene.rootNode.addChildNode(planeNode)
        

      结果就是这样:

      【讨论】:

        猜你喜欢
        • 2018-04-14
        • 1970-01-01
        • 2011-05-25
        • 2015-07-29
        • 2021-01-15
        • 1970-01-01
        • 2018-01-30
        • 1970-01-01
        • 2017-05-19
        相关资源
        最近更新 更多