Object attribute of textgeometry

Currently, I am immersed in a project that involves creating web components using Three.js. One of the challenges I face is generating objects for these components, particularly those with text attributes. My goal is to encapsulate the text mesh within a THREE.Group() object to enhance accessibility and facilitate future modifications.

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;
    },

    ...
};

The challenge arises when trying to instantiate the object using generic code for instantiation and display as shown below:

<!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>

An error message is thrown during execution:

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

The issue seems to stem from line 10 in the Button.js file where this._textMesh gets added to this._geo.

I have explored alternative methods for generating text meshes without relying on textLoader, but encountered issues with displaying the text without any specific console errors...

If anyone has insights or solutions to this perplexing problem, your assistance would be greatly appreciated!

Answer №1

The issue arises because when you call the createText() method, it returns a null value instead of a mesh.

A more straightforward version of your code can be seen below:

function createText() {
  var text = null;

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

  return text;
}

It's essential to understand how asynchronous functions work in JavaScript. When you invoke the createText() method, three things occur:

  1. The variable text is set to null
  2. The request to load the font begins
  3. The value of text (which remains null at this point) is returned

Why does this happen? The HTTP request takes quite some time to fetch a result, and the callback function that receives the loaded font gets executed long after the value has been returned. Thus, even though the mesh is created eventually, it's no longer relevant as the return has already occurred.

To address this issue, there are ways to ensure the font is loaded before proceeding to add the object to the group.

You could consider implementing it like this:

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

Alternatively, you can guarantee the font is preloaded before any further actions take place.

In addition, if you have a need to render a considerable amount of text, using text meshes might not be the most efficient solution due to the high number of vertices and processing required for their rendering.

Exploring alternative methods for text rendering could be beneficial. Some options include:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Step-by-step guide on displaying SVG text on a DOM element using Angular 8

I have a FusionChart graph that I need to extract the image from and display it on the same HTML page when the user clicks on the "Get SVG String" button. I am able to retrieve the SVG text using this.chart.getSVGString() method, but I'm unsure of ho ...

Minimize an array by organizing objects based on the proximity of their numbers

My array contains the following data: [ { "begin": 870, "end": 889, "spanType": ["plan", "gt-plan"] }, { "begin": 890, "end": 925, "spanType": ["plan", "gt-plan"] }, { "begin": 926, "end": 938, "spanType": ["plan", "gt-plan"] }, { "begin": 939, ...

I have no interest in using vanilla JavaScript to search for data in the database

I have a class assignment that requires the use of XMLHTTPREQUEST and JSON without using Jquery. The task involves searching for specific data through custom inputs. However, when I perform the search, I encounter this error which I'm unsure how to r ...

Utilizing Jquery select2 to enhance user experience by organizing JSON data with optgroup and

Currently, I am working with select2 in conjunction with spring mvc. The data I need to display is retrieved from my controller and should be displayed as options. However, I would like these options to be grouped within optgroups while also incorporating ...

The button is being obscured by an invisible element at coordinates (x,y), making it unclickable

Having trouble with Selenium and Chrome Webdriver when trying to click a button due to an invisible element <div class="modal-overlay" style="display: block;"></div> covering the entire page. How can I navigate around this obstacle? I attempte ...

What's the best way to showcase the time on the x-axis of a Flot line graph?

My goal is to display time intervals between the minimum and maximum values within a specific time range. For example: 2015-04-30 10:20:00 and 2015-04-30 10:30:00 on the x-axis. I need to fetch values from a database where the datetime is stored in the fo ...

Deactivate the backface culling feature when loading an imported .obj file in three.js

I'm struggling with disabling wireframe rendering on the rear side of my vehicle. Any ideas on how to deactivate backface culling in wireframe mode for three.js? Check out this link for a helpful image ...

Is there a way to continuously click on a button 99 times or until the code finishes running?

Need Assistance, Please Assist. I am encountering an issue where I have the same type of skip button with identical name and id properties for all products, but only the xpath changes. Can you provide guidance on how to efficiently click on 99 similar ski ...

What are some techniques for saving a Model imported with ColladaLoader in Three.js?

I have encountered an issue since the migration from Three.js version r68 to r69. The ColladaLoader now returns a Scene instead of an Object3D. How can I retrieve the loaded Object3D in this new setup? My goal is to store the loaded Object in a variable ...

What is the best method to transfer an array as a parameter from an Ipython notebook to an HTML file that includes specific javascript functions?

I have a unique HTML file named "file.html" that includes a distinctive JavaScript function described below: The Unique file.html <html> <head> </head> <script> function customFunction() { perform an action using ...

Creating Dynamic Divs in ASP.NET

Attempting to dynamically create a Div by clicking a button has been a challenge for me. I found a helpful link here: After referring to the link, I created the following code on the server side (.cs page): public static int i = 0; protected void Bu ...

Adjust counter to allocate points based on team in Vue.js

Currently, I am tackling a Vue.js 3 school assignment that involves a dynamic number of teams competing in a football championship. The team data is stored in a JSON format and accessed via an API. The task at hand requires selecting two teams - one repres ...

Toggle <DIV> Visibility Depending on <SELECT> Selection

Can someone please assist me in figuring out why this code, which works perfectly on jsFiddle, is not functioning on my website? I have spent hours trying to resolve this issue, but no matter what I do, I cannot seem to get it to work. I suspect it may be ...

The button should only be visible when the input is selected, but it should vanish when a different button within the form is

Having an issue with displaying a button when an input field is in focus. The "Cancel" button should appear when a user interacts with a search bar. I initially used addEventListener for input click/focus to achieve this, but ran into a problem: on mobile ...

Guide on creating a service in AngularJS that calls a function from a module utilizing the base module

I am currently developing a versatile service intended for use across various independent websites. However, there are certain instances where the service needs to execute different code based on the specific website it is implemented in. My goal is to mai ...

Inject some content into the page with the power of jQuery

Currently working with jQuery, I have a div containing H2 tags. <div id="preload"><h2></h2></div> I'm looking to understand how to use jQuery to insert text inside the <h2> tags The expected outcome should be: <div ...

Is there a method to automatically create .stories.ts files in Angular Storybook?

I am seeking a way to automatically create a .stories.ts file within a component folder after executing the command ng g component my-component. The desired outcome should resemble this structure: my-component -my-component.component.html . ...

Tips for exporting an array of dynamic JSON objects to CSV using Angular

I am facing a challenge in exporting an array of JSON objects to CSV as the number of key-value pairs can vary, leading to additional columns in some objects. Currently, I am using the Angular2CSV package for export functionality, but it requires all colum ...

Enhancing tooltips in a multi-series chart with Highcharts - incorporating suffixes

Apologies for my lack of experience once again. I am now looking to enhance my tooltip by adding a suffix to indicate % humidity and °C for temperature. While the code derived from ppotaczek with some tweaks is working well, I've been struggling to a ...

Transform an array of objects into one unified object

Suppose you have an array like this - [ { name: "abc", value: "1" }, { name: "xyz", value: "2" }, { name: "abc", value: "3" }, { name: "abc", ...