three.jsで作成した3Dモデルがあります。いくつかのデータに基づいて、小さなテキスト ラベルで装飾された一連の矢印を作成したいと考えています。これらのラベルは 2D である必要があります。
別のキャンバス要素を使用してテクスチャを作成し、それを 3D モデルで使用するか、3D モデルのキャンバス要素の上に HTML を使用します。
これをどうしようか迷っています。これを行う「正しい」方法はどれですか? 提案やサンプルコードは大歓迎です!
three.jsで作成した3Dモデルがあります。いくつかのデータに基づいて、小さなテキスト ラベルで装飾された一連の矢印を作成したいと考えています。これらのラベルは 2D である必要があります。
別のキャンバス要素を使用してテクスチャを作成し、それを 3D モデルで使用するか、3D モデルのキャンバス要素の上に HTML を使用します。
これをどうしようか迷っています。これを行う「正しい」方法はどれですか? 提案やサンプルコードは大歓迎です!
テキストが常に一番上に表示され(たとえば、オブジェクトが他の何かによってブロックされている場合でも、そのテキストラベルは引き続き表示され、他のすべての上に表示されます)、テキストが影響を受けないことを気にしない場合ライト/シャドウなどのレンダリングの場合、HTMLが最も簡単な方法です。
サンプルコードは次のとおりです。
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);
テキストを配置するy座標とx座標を(それぞれ)style.top変数とstyle.left変数に200で置き換えます。これらは正の値になります。ここで、(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;
}
事前にcamera.updateMatrixWorld()を呼び出していることを確認してください。
3Dシーンの一部としてキャンバスオブジェクトからのテキスト(または任意の画像)を実際に含めたい場合は、 http://stemkoski.github.com/Three.js/Texture-From-Canvasでサンプルコードを確認してください。 html
更新: このメソッドは現在非推奨であり、CPU が重いため、使用しないでください。
three.jsベースの別のソリューションを見つけました。
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};
このテキストを動的に編集するには、
var textShapes = THREE.FontUtils.generateShapes( text, options );
var text = new THREE.ShapeGeometry( textShapes );
textMesh.geometry = text;
textMesh.geometry.needsUpdate = true;
あなたのためにそれを行うモジュールを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)
2D キャンバスを作成し、css を使用して webgl キャンバスの上部に配置できます。次に、2D キャンバス コンテキストによって提供されるctx.fillText(text,x,y)
またはメソッドを使用して、その上にテキストを描画できます。ctx.strokeText(text,x,y)
このメソッドを使用すると、矢印やメーターなど、テキスト以外のものを描画できます。
@kronuus が提案する方法を使用して、ポイントを 3D 空間から 2D 空間に変換できます。
@LeeStemkoski による応答は非常に役に立ちました。ただし、テキストが矢印に追従するように、つまり矢印が移動したり、回転したりした場合に備えて、コードにわずかな変更を加える必要があります。
次のコードを参照してください
var canvas1 = document.createElement('canvas');
var context1 = canvas1.getContext('2d');
context1.font = "Bold 10px Arial";
context1.fillStyle = "rgba(255,0,0,1)";
context1.fillText('Hello, world!', 0, 60);
// canvas contents will be used for a texture
var texture1 = new THREE.Texture(canvas1)
texture1.needsUpdate = true;
var material1 = new THREE.MeshBasicMaterial({ map: texture1, side: THREE.DoubleSide });
material1.transparent = true;
var mesh1 = new THREE.Mesh(
new THREE.PlaneGeometry(50, 10),
material1
);
mesh1.position.set(25, 5, -5);
mesh1.rotation.x = -0.9;
shape.add(mesh1);
// Note that mesh1 gets added to the shape and not to the scene
scene.add(shape)
ご覧のとおり、テキスト ( mesh1
)をshape
シーンに追加するのではなく、 (「矢印」)に追加するのがコツです。
これが役立つことを願っています。