2016-11-10 12 views
1

我目前正在創建一個項目以創建具有三個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/),但文字不顯示,我沒有在控制檯的錯誤信息......

不任何人有關於如何解決這個問題的想法? 在此先感謝您的幫助!

回答

1

僅僅因爲您實際上沒有返回網格物體,而是從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)); 
    }) 
} 

或者你確保字體已加載任何在這之前發生。

還有一點需要注意:我不知道你的用例,但是如果你需要渲染大量的文本,使用文本網格可能會浪費資源(因爲頂點和計算的數量很多參與渲染它們)。

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

+0

非常感謝您的快速回答! 儘管如果您不介意,我想獲得一些其他信息。 - 你說「確保字體已經加載」。我如何預加載字體? - 我試過了createTextMesh(字體)以下,但仍文本不顯示: 'createTextMesh:功能(字體){VAR = textGeometry新THREE.TextGeometry(this._text,{ 字體:字體, size:this._textSize, height:this._textSize }); 返回新的THREE.Mesh(textGeometry,this._textMaterial); },' 任何想法爲什麼? 謝謝! – fums