我目前正在开发一个项目来创建包含三个js的Web组件。为此,我必须为不同的组件创建对象。 我有几个问题来创建具有text作为属性的对象。 我想在THREE.Group()对象中添加文本的网格,以便在需要添加修改时使其更易于访问和使用。
var Button = {
init : function(text, textSize, textFont, textMaterial, other attributes ...) {
this._geo = new THREE.Group();
this.createTextDesign(text, textSize, textFont, textMaterial);
this._textMesh = this.createText()
this._geo.add(this._textMesh);
...
},
createTextDesign : function() {
this._text = text;
this._textMaterial = textMaterial;
this._textFont = textfont;
if (textSize == "lg") {
this._textSize = 2.5;
} else if (textSize == "sm"){
this._textSize = 1.5;
} else if (textSize == "xs"){
this._textSize = 1;
} else {
this._textSize = 2;
},
createText : function(){
var text = null;
var fontLoader = new THREE.FontLoader();
fontLoader.load('fonts/' + this._textFont + '.typeface.json', function(font) {
var textGeometry = new THREE.TextGeometry(this._text, {
font: font,
size: this._textSize,
height: this._textSize
});
fontLoader.load();
text = new THREE.Mesh(textGeometry, this._textMaterial);
});
return text;
},
getGroup : function(){
return this._geo;
},
...
};
问题在于,当我尝试使用以下通用代码(实例化+显示对象)实例化此对象时:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js - ASCII Effect</title>
<meta charset="utf-8">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="js/build/three.js"></script>
<script src="components/Button.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var mat2 = new THREE.MeshBasicMaterial( {color: 0xff0000} );
var mat3 = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var mat4 = new THREE.MeshBasicMaterial( {color: 0x0000ff} );
var button = Object.create(Button);
button.init("test", "lg", "optimer_regular", mat2, mat3, mat4);
scene.add(button.getGroup());
camera.position.z = 50;
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
我收到以下错误:
THREE.Object3D.add: object not an instance of THREE.Object3D. nullthree.js:10826:5
.add() three.js:10826
Button.init() Button.js:10
<anonymous> test4.html:31
使用button.js:10是我将this._textMesh添加到this._geo的行。
我还尝试了不同的技术来创建文本网格而不使用textLoader(例如:http://blog.andrewray.me/creating-a-3d-font-in-three-js/),但文本没有显示,我在控制台中没有任何错误消息...
有人知道如何解决这个问题吗? 在此先感谢您的帮助!
答案 0 :(得分:1)
抛出错误只是因为您实际上没有返回网格,而是从null
- 方法返回createText()
。
您的代码的简化版本如下所示:
function createText() {
var text = null;
fontLoader.load(fontUrl, function(font) {
text = createTextMesh(font);
})
return text;
}
现在,您需要了解javascript中的异步函数是如何工作的。在此示例中,当您致电createText()
时会发生三件事:
text
初始化为null
text
(此时始终为null
)的值。为什么? HTTP-Request采用(就代码的速度而言)年龄,最终返回结果。因此,在已经返回值之后很长一段时间内调用接收加载字体的回调函数。它仍然会创建网格,但结果不再使用,因为返回已经发生。
有一些选项可以解决这个问题,但无论如何,在将对象添加到组之前,您需要等到字体加载完毕。
你可以这样试试:
function addTextMesh(parent) {
fontLoader.load(fontUrl, function(font) {
parent.add(createTextMesh(font));
})
}
或者你确定在发生任何变化之前已经加载了字体。
还有一点需要注意:我不知道你的用例,但如果你需要渲染大量的文本,使用文本网格可能会浪费资源(因为涉及大量的顶点和计算在渲染它们)。
查看渲染文本的其他替代方案可能是个好主意: