2017-08-15 64 views
1

我在https://jsfiddle.net/72mnd2yt/1/有一些代码,它不显示我想绘制的雪碧。我试图按照https://stemkoski.github.io/Three.js/Sprite-Text-Labels.html的代码并逐行阅读,但我不确定我错在哪里。有人会介意看看它吗?雪碧没有显示

下面是一些相关的代码:

// picture 
var getPicture = function(message){ 
    var canvas = document.createElement('canvas'); 
    canvas.width = "100%"; 
    canvas.height = "100%"; 

    var context = canvas.getContext('2d'); 
    context.font = "10px"; 
    context.fillText(message, 0, 10); 
    var picture = canvas.toDataURL(); 
    // return picture; 
    return canvas; 
}; 

// let there be light and so forth... 
var getScene = function(){ 
    var scene = new THREE.Scene(); 
    var camera = new THREE.PerspectiveCamera(
    70, 
    $('body').width(), 
    $('body').height(), 
    1, 
    1000 
); 

    var light = new THREE.PointLight(0xeeeeee); 
    scene.add(camera); 
    scene.add(light); 

    var renderer = new THREE.WebGLRenderer(); 
    renderer.setClearColor(0xefefef); 
    renderer.setSize($('body').width(), $('body').height()); 

    camera.position.z = -10; 
    camera.lookAt(new THREE.Vector3(0, 0, 0)); 

    return [scene, renderer, camera]; 
}; 

// now for the meat 
var getLabel = function(message){ 
    var texture = new THREE.Texture(getPicture(message)); 
    var spriteMaterial = new THREE.SpriteMaterial(
    {map: texture } 
); 
    var sprite = new THREE.Sprite(spriteMaterial); 
    //sprite.scale.set(100, 50, 1.0); 
    return sprite 
}; 

var setup = function(){ 
    var scene; 
    var renderer; 
    var camera; 
    [scene, renderer, camera] = getScene(); 
    $('body').append(renderer.domElement); 

    var label = getLabel("Hello, World!"); 
    scene.add(label); 

    var animate = function(){ 
    requestAnimationFrame(animate); 
    renderer.render(scene, camera); 
    }; 

    animate(); 
}; 


setup(); 

回答

2

的几点:

1)canvas.width = "100%"canvas.width = "100"(画布大小被认为是像素)。与canvas.height相同。

2)$('body').height()为0,因此渲染器画布不可见(您可以在开发工具中查看它,它在元素树中,但压扁到0px高)。我对jQuery一无所知,所以不确定这是为什么,但我会推荐使用window.innerHeightwindow.innerWidth。所以renderer.setSize(window.innerWidth, window.innerHeight)。您还需要在相机初始化中进行此更改。

3)说到相机初始化,当宽度和高度作为单独的参数传递时,应该只有宽高比参数。 See the docs。所以
var camera = new THREE.PerspectiveCamera(70, window.innerWidth, window.innerHeight, 1, 1000)
成为
var camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 1, 1000)

4)由于纹理被认为是静态的,你需要的东西添加到该部分:

var texture = new THREE.Texture(getPicture(message)) 
texture.needsUpdate = true // this signals that the texture has changed 

这是一个一次性的标志,所以你需要如果您想要动态纹理,则每次画布更改时都要设置它。您不必每次都制作一个新的THREE.Texture,只需在渲染循环中添加texture.needsUpdate(或者如果您希望提高效率,只需在需要更改纹理时触发)。 See the docs,在.needsUpdate之下。


在这一点上,它应该工作。这里有一些进一步的事情要考虑:

5)而不是使用Texture你可以使用CanvasTexture,它为你设置.needsUpdate。你发布的小提琴是使用Three.js r71,它没有它,但新版本。这将是这样的:

var texture = new THREE.CanvasTexture(getPicture(message)); 
// no needsUpdate necessary 

6)看起来你已经根据注释掉return picture这条道路上,但你可以使用从画布产生任何canvas元素,或数据网址纹理。如果getPicture现在返回一个数据的网址,试试这个:

var texture = new THREE.TextureLoader().load(getPicture(message)) 

您也可以间接地使用数据链接与Texture

var img = document.createElement('img') 
var img = new Image() 
img.src = getPicture(message) 
var texture = new THREE.Texture(img); 
texture.needsUpdate = true 

如果没有,只是坚持TextureCanvasTexture,双方将采取画布元素。 Texture可以通过传递一个src设置为数据url的图像元素来间接获取url。


拨弄修复概述: https://jsfiddle.net/jbjw/x0uL1kbh/