three.js 实现立体几何的文本标签

最近在做一个基于three.js实现立体几何的项目,碰到一个问题,如何给球体加上文字标签,探索了几种实现方法。

二维文字标签

1.通过CSS2DObject创建二维对象

var earthDiv = document.createElement( 'div' );
earthDiv.className = 'label';
earthDiv.textContent = 'Earth';
earthDiv.style.marginTop = '-1em';
var earthLabel = new CSS2DObject( earthDiv );
earthLabel.position.set( 0, EARTH_RADIUS, 0 );
earth.add( earthLabel );
var moonDiv = document.createElement( 'div' );
moonDiv.className = 'label';
moonDiv.textContent = 'Moon';
moonDiv.style.marginTop = '-1em';
var moonLabel = new CSS2DObject( moonDiv );
moonLabel.position.set( 0, MOON_RADIUS, 0 );
moon.add( moonLabel );

2.利用CSS2DRenderer将二维对象append到dom节点中,CSS2DRenderer会将所有的CSS2DObject(HTMLELEMENT)包裹在一个div容器,append到dom节点中

labelRenderer = new CSS2DRenderer();
labelRenderer.setSize( window.innerWidth, window.innerHeight );
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
document.body.appendChild( labelRenderer.domElement );

3.效果图(来源于官网demo, 其中moom和earth为文字标签)

three.js 实现立体几何的文本标签_第1张图片

4.使用场景及局限

用于标记整个立体几何,不适用于标记立体几何的局部位置

三维文字标签

基于三维空间中物体的灵活性,三维文字标签满足了标记立体几何局部位置的需求。
实现思路:

  • 由于Sprite是一个总是面朝着摄像机的平面,很贴合标签的使用场景,选择其作为标签的原形;
  • 文字的实现有两种方式: textGeometry和canvasTexture贴图,textGeometry实际上渲染出立体的文字,成本较高;而canvas的方式较轻量,本文采用了后者。
  • 文字和Sprite组合起来则成为三维文字标签,通过position即可定位到标记的地方

1.离屏canvas测量文本的width(用于确定实际canvas的宽度)

const offScreenCanvas = document.createElement("canvas");
const offScreenCtx = offScreenCanvas.getContext("2d");
offScreenCtx.font = "14px 黑体";
const txt = '标签';
const textWidth = offScreenCtx.measureText(txt).width;

2.绘制文字到canvas中作为texture

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const txt = '标签';
if (ctx !== null) {
canvas.width = (textWidth + padding 2) pixelRatio;
canvas.height = 18 * pixelRatio;
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
ctx.font = "14px 黑体";
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, textWidth + padding * 2, 18);
ctx.fillStyle = "#000";
ctx.fillText(txt, padding, 14);
}
const texture = new THREE.CanvasTexture(canvas);

3.渲染Sprite

const spriteMaterial = new THREE.SpriteMaterial( { map: texture, sizeAttenuation: false } );
const label = new THREE.Sprite( spriteMaterial );
const scaleY = 0.1;
const scaleX = scaleY * canvas.width / canvas.height;
label.position.copy(vertice);
// sprite默认会令canvas变形 需要通过scale调整比例
label.scale.set(scaleX, scaleY, 1);

你可能感兴趣的:(three.js,javascript)