and*_*ers 31 html javascript three.js
我有三个模型,我在three.js创建.基于一些数据,我想创建一组由小文本标签装饰的箭头.这些标签应为2D.
看起来我有两种选择:使用单独的canvas元素来创建纹理,然后在3D模型中使用它,或者在3D模型的canvas元素上使用HTML.
我想知道如何解决这个问题.这是"正确"的方法吗?任何建议和示例代码都非常欢迎!
kro*_*uus 39
如果您不介意文本将始终位于顶部(例如,如果对象被其他内容阻止,则其文本标签仍然可见并且在其他所有内容之上),并且文本不会受到任何影响渲染像灯光/阴影等,然后HTML是最简单的方式去imho.
以下是一些示例代码:
var text2 = document.createElement('div');
text2.style.position = 'absolute';
//text2.style.zIndex = 1; // if you still don't see the label, try uncommenting this
text2.style.width = 100;
text2.style.height = 100;
text2.style.backgroundColor = "blue";
text2.innerHTML = "hi there!";
text2.style.top = 200 + 'px';
text2.style.left = 200 + 'px';
document.body.appendChild(text2);
Run Code Online (Sandbox Code Playgroud)
在style.top和style.left变量中替换为您希望放置文本的y和x坐标(分别).它们将是正值,其中(0,0)是画布的左上角.有关如何从画布中的3D点投影到浏览器窗口中的2D点(像素点)的一些指导,请使用如下代码段:
function toXYCoords (pos) {
var vector = projector.projectVector(pos.clone(), camera);
vector.x = (vector.x + 1)/2 * window.innerWidth;
vector.y = -(vector.y - 1)/2 * window.innerHeight;
return vector;
}
Run Code Online (Sandbox Code Playgroud)
确保您事先调用了camera.updateMatrixWorld().
Lee*_*ski 19
如果您确实想要将画布对象中的文本(或任何图像)作为3D场景的一部分包含在内,请查看示例代码:http: //stemkoski.github.com/Three.js/Texture-From-Canvas. HTML
Ser*_*Pie 17
看看 演示.
TextGeometry消耗大量内存,您需要加载一个字体,其中包含您将使用的每个字母的几何.如果场景中有超过100个文本网格,我的浏览器会崩溃.
您可以在画布上绘制文本并通过a将其包含在场景中Sprite.它的问题是你需要计算字体大小.如果您有移动相机,则需要定期计算字体大小.否则,如果您使用相机太靠近文本,文本将变得模糊.
我写了一个类TextSprite,它根据相机的距离和渲染器元素的大小自动计算出最佳的字体大小.诀窍是使用Object3D.onBeforeRender类的回调,它接收相机和渲染器.
let sprite = new THREE.TextSprite({
text: 'Hello World!',
fontFamily: 'Arial, Helvetica, sans-serif',
fontSize: 12,
fillColor: '#ffbbff',
});
scene.add(sprite);
Run Code Online (Sandbox Code Playgroud)
您还可以动态更改文本,文本大小和字体.
sprite.text = 'Hello Stack Overflow!';
sprite.fontFamily = 'Tahoma, Geneva, sans-serif';
sprite.fontSize = 24;
Run Code Online (Sandbox Code Playgroud)
更新:此方法现在已弃用并且CPU很重,请勿使用它.
我发现另一个只有三个基于解决方案的解决方案,
var textShapes = THREE.FontUtils.generateShapes( text, options );
var text = new THREE.ShapeGeometry( textShapes );
var textMesh = new THREE.Mesh( text, new THREE.MeshBasicMaterial( { color: 0xff0000 } ) ) ;
scene.add(textMesh);
// Example text options : {'font' : 'helvetiker','weight' : 'normal', 'style' : 'normal','size' : 100,'curveSegments' : 300};
Run Code Online (Sandbox Code Playgroud)
现在动态编辑此文本,
var textShapes = THREE.FontUtils.generateShapes( text, options );
var text = new THREE.ShapeGeometry( textShapes );
textMesh.geometry = text;
textMesh.geometry.needsUpdate = true;
Run Code Online (Sandbox Code Playgroud)
我已经在NPM上发布了一个模块,可以帮助你:https://github.com/gamestdio/three-text2d
它允许您拥有Sprite或Mesh使用渲染文本而无需手动处理画布.
例:
var Text2D = require('three-text2d').Text2D
var text = new Text2D("Hello world!", { font: '30px Arial', fillStyle: '#000000', antialias: true })
scene.add(text)
Run Code Online (Sandbox Code Playgroud)
您可以创建2D画布并使用css将其定位到webgl画布的顶部.然后,您可以使用2d画布上下文提供的ctx.fillText(text,x,y)或ctx.strokeText(text,x,y)方法在其上绘制文本.通过使用此方法,您可以绘制除文本之外的其他内容,例如箭头和米.
您可以使用@kronuus建议的方法将点从3d转换为2d空间.