javascript - 文本几何作为对象属性

标签 javascript three.js

我目前正在开发一个使用三个 js 创建 Web 组件的项目。为了做到这一点,我必须为不同的组件创建对象。 我在创建以文本为属性的对象时遇到几个问题。 我想在 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/ ),但文本不显示,并且控制台中没有任何错误消息...

有人知道如何解决这个问题吗? 预先感谢您的帮助!

最佳答案

抛出错误只是因为您实际上没有返回网格,而是从 createText() 方法返回 null

代码的简化版本如下所示:

function createText() {
  var text = null;

  fontLoader.load(fontUrl, function(font) {
    text = createTextMesh(font);
  })

  return text;
}

现在,您需要了解 javascript 中的异步函数是如何工作的。在此示例中,当您调用 createText() 时,会发生三件事:

  1. 变量text初始化为null
  2. 加载字体的请求已开始
  3. 返回 text 的值(此时始终为 null)。

这是为什么呢? HTTP 请求需要很长时间(就代码的速度而言)才能最终返回结果。因此,在返回值很长时间后,会调用接收加载字体的回调函数。然后它仍然创建网格,但结果不再使用,因为返回已经发生。

有一些选项可以解决此问题,但无论如何,您都需要等到字体加载后才能将对象添加到组中。

你可以这样尝试:

function addTextMesh(parent) {
  fontLoader.load(fontUrl, function(font) {
    parent.add(createTextMesh(font));
  })
}

或者您确保在发生任何情况之前字体已经加载。

还有一点:我不知道你的用例,但是如果你需要渲染大量文本,使用文本网格可能会浪费资源(因为涉及大量的顶点和计算)渲染它们)。

看看其他渲染文本的替代方案可能是个好主意:

关于javascript - 文本几何作为对象属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40531559/

相关文章:

javascript - 3D 切片网络应用程序 Javascript 和 Three.js

javascript - 将 GeometryUtils.merge() 迁移到 geometry.merge()

javascript - 解码克隆的 div 的 HTML 内容

javascript - 如何退出超时函数的实例?

javascript - 使用 webpack 将多个 ES6 类捆绑到一个文件中,以便在脚本标签中导入

javascript - 对话框页面中的 SharePoint 2010 客户端 JavaScript 代码

javascript - CSS3D矩阵生成

javascript - enzyme 调用法

javascript - 对象部分的阴影未显示 - Three.js

html - 如何使用 HTML5 Web Audio API 来录制我的声音