2017-07-18 63 views
1

我试图在下面的代码中将一个文本字符串(SCNText)放入一个框(SCNBox)中。框的大小看起来是正确的,但文本不在框的正中。任何想法或解决方案?由于SceneKit - SCNText居中不正确

let geoText = SCNText(string: "Hello", extrusionDepth: 1.0) 
geoText.font = UIFont (name: "Arial", size: 8) 
geoText.firstMaterial!.diffuse.contents = UIColor.red 
let textNode = SCNNode(geometry: geoText) 

let (minVec, maxVec) = textNode.boundingBox 
scnScene.rootNode.addChildNode(textNode) 

let w = CGFloat(maxVec.x - minVec.x) 
let h = CGFloat(maxVec.y - minVec.y) 
let d = CGFloat(maxVec.z - minVec.z) 

let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0) 
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.5) 
scnScene.rootNode.addChildNode(boxNode) 

The text is not the center of the box

编辑:我添加了一个debugOptions showBoundingBoxes字符串(不使用SCNBox节点)的新形象,看看它的边框

enter image description here

解决方案1:

从vdugnist的回答3210

,我创造的人谁愿意操场代码来测试:

import UIKit 
import SceneKit 
import PlaygroundSupport 

var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 600)) 
var scene = SCNScene() 
sceneView.scene = scene 
PlaygroundPage.current.liveView = sceneView 

let geoText = SCNText(string: "Hello", extrusionDepth: 1.0) 
geoText.font = UIFont (name: "Arial", size: 12) 
geoText.firstMaterial!.diffuse.contents = UIColor.red 
let textNode = SCNNode(geometry: geoText) 

let (minVec, maxVec) = textNode.boundingBox 
textNode.position = SCNVector3(x: (minVec.x - maxVec.x)/2, y: minVec.y - maxVec.y, z: 0) 
textNode.pivot = SCNMatrix4MakeTranslation((maxVec.x - minVec.x)/2, 0, 0) 
scene.rootNode.addChildNode(textNode) 

let w = CGFloat(maxVec.x - minVec.x) 
let h = CGFloat(maxVec.y - minVec.y) 
let d = CGFloat(maxVec.z - minVec.z) 

let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0) 
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.5) 
let boxNode = SCNNode(geometry: geoBox) 
boxNode.position = SCNVector3Make((maxVec.x - minVec.x)/2 + minVec.x, (maxVec.y - minVec.y)/2 + minVec.y, 0); 
textNode.addChildNode(boxNode) 

enter image description here

解决方案2:

我需要移动文本位置零(0 ,0,0),而不是移动文本和周围的框,因此我继续更改解决方案1的文本的主轴。现在代码如下:

import UIKit 
import SceneKit 
import PlaygroundSupport 


var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 600)) 
var scene = SCNScene() 
sceneView.scene = scene 
PlaygroundPage.current.liveView = sceneView 


let geoText = SCNText(string: "Hello", extrusionDepth: 1.0) 
geoText.font = UIFont (name: "Arial", size: 12) 
geoText.firstMaterial!.diffuse.contents = UIColor.red 
let textNode = SCNNode(geometry: geoText) 

let (minVec, maxVec) = textNode.boundingBox 
textNode.pivot = SCNMatrix4MakeTranslation((maxVec.x - minVec.x)/2 + minVec.x, (maxVec.y - minVec.y)/2 + minVec.y, 0) 
scene.rootNode.addChildNode(textNode) 

let w = CGFloat(maxVec.x - minVec.x) 
let h = CGFloat(maxVec.y - minVec.y) 
let d = CGFloat(maxVec.z - minVec.z) 

let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0) 
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.6) 
let boxNode = SCNNode(geometry: geoBox) 
scene.rootNode.addChildNode(boxNode) 

回答

1

SCNText与其他几何图形的区别在于SCNText原点位于左下角。在其他几何形状中,它是底部中心。

要解决的父节点文本位置可以设置其pivotPoint.x至宽度的一半:

SCNVector3 min, max; 
[textNode getBoundingBoxMin:&min max:&max]; 
textNode.pivot = SCNMatrix4MakeTranslation((max.x - min.x)/2, 0, 0); 

要解决的子节点位置,你应该设置自己的地位宽度加分的一半:

SCNVector3 min, max; 
[textNode getBoundingBoxMin:&min max:&max]; 
subnode.position = SCNVector3Make((max.x - min.x)/2 + min.x, (max.y - min.y)/2 + min.y, 0); 
+0

谢谢,但看起来它不是一个解决方案(我已经尝试过,但它更糟糕 - 也许我不明白你的想法?)。逻辑上,在我的问题图像中,中心点对于x轴和y轴都不在正确的位置。你的答案只是试图修复x,显然这是不够的。这是最好的,如果你在这里发布完整的修复代码。 – Tony

+1

您是否可以尝试使用我的第二个解决方案中的坐标将盒子节点添加为文本节点的子节点而不是根节点? 我在代码中看到的问题是,您将从textNode获取boundingBox,该文本将在textNode坐标系中返回,并在rootNode坐标系中使用它们。 – vdugnist

+0

明白了,它现在运作良好! – Tony

0

找到你需要添加边框的中心(未减去)最小和最大您可以通过2

textNode.position = SCNVector3(x: (minVec.x + maxVec.x)/2, y: minVec.y + maxVec.y, z: 0) 
+0

对不起,但它不是正确的答案。我以点(0,0,0)为中心,与框类似,不要按照您的建议远离文本。 – Tony

0

划分之前,我想你可能会被SCNText起源的异常处理被咬伤。 IIRC Y零点位于字符串的基线,而不是在下行线的底部。

打开showBoundingBoxesdebugOptions看看是否有帮助。

+0

我已打开所有调试选项并已检查。一切看起来不错。因此我不知道。也许这是一个API错误(因为代码非常简单,逻辑非常清晰)! – Tony

+0

这不太可能是一个API错误。但由于它不能按照您的期望工作,因此它可能是一个文档错误。我们可以看到打开边界框的截图吗? –

+0

我无法在此添加图像(在此评论中)。因此,我编辑了我的问题来添加该图像。更多信息更好反正 – Tony