在三维模型场景展示中,常常会须要对各个模型加上笔墨标签,而无论三维场景如果旋转变换一样平常笔墨标签总是须要面向摄像机方向,这时候代表深度的z坐标失落去浸染,只需用到x,y坐标。这时候须要把三维坐标转换为基于屏幕上的二维坐标。
三维模型上加笔墨标签最常用的方法该当便是(DOM + CSS)基于传统html5的笔墨实现,用于添加描述性叠加笔墨的方法。详细实现是声明一个绝对定位的DIV,并且担保z-index够大,担保能够显示在3D场景之上。然后打算三维坐标对应的二维坐标,根据二维坐标去设置DIV的left和top属性,让DIV在须要的位置进行展示。这种办法实现大略,DIV可方便利用页面CSS效果进行UI设置。
在三维场景上增加一个立方体,在球体和立方体上分别加上个笔墨标签。
添加立方体模型:
var cubeMaterial = new THREE.MeshStandardMaterial({color:0x00ffff});
cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.set(300,100,100);
scene.add(cube);
页面上添加两个div及css样式:
<div id="info1">这是球体</div>
<div id="info2">这是立方体</div>
#info1 {
position: absolute;
top: 0;
width: 100px;
height: 50px;
text-align: center;
z-index: 100;
display:block;
padding: 10px;
background: rgba(255, 255, 255, 0.8);
line-height: 1;
border-radius: 5px;
}
#info2 {
position: absolute;
top: 0;
width: 100px;
height: 50px;
text-align: center;
z-index: 100;
display:block;
padding: 10px;
background: rgba(255, 255, 255, 0.8);
line-height: 1;
border-radius: 5px;
}
在OnRender方法中写坐标系转换代码:
var halfWidth=window.innerWidth/2;var halfHeight=window.innerHeight/2;var vectSphere = new THREE.Vector3(sphere.position.x,sphere.position.y,sphere.position.z);var posiSphere =vectSphere.project(camera);;$("#info1").css({left:posiSphere.xhalfWidth+halfWidth,top:-posiSphere.yhalfHeight+halfHeight,});var vectCube = new THREE.Vector3(cube.position.x,cube.position.y,cube.position.z);var posiCube =vectCube.project(camera);$("#info2").css({left:posiCube.xhalfWidth+halfWidth,top:-posiCube.yhalfHeight+halfHeight,});
这样无论我怎么旋转缩放或移动三维模型,文本DIV标签都能显示在得当的位置。
在threejs三维场景中添加笔墨有很多不同的方法,上面说的DIV+CSS的办法该当是最大略也最快速办法。
如果希望在三维模型中绘制文本,可以把笔墨图片用作Texture(纹理),绘制在模型表面。
另一种常用的办法是利用three.js自带的笔墨几何体来添加3d或2d的笔墨,这种方法可以创建能够由程序改变的、动态的3D笔墨,可以创建一个其几何体为THREE.TextGeometry的实例的网格。须要把字体文件添加进来,在示例font目录下有json格式的几种字体。
示例:
var loader = new THREE.FontLoader(); loader.load( 'fonts/SimHei_Regular.json', function ( font ) {var geometry = new THREE.TextGeometry( 'Hello three.js!测试', {font: font,size: 50,height: 1,curveSegments: 12,bevelEnabled: true,bevelThickness: 10,bevelSize: 8,bevelSegments: 5} );var fontMaterial = new THREE.MeshLambertMaterial({ color: 0x808080 }); var fontModel = new THREE.Mesh(geometry,fontMaterial); scene.add(fontModel);
接着我们在添加一个2d笔墨
var font2dMaterial = new THREE.MeshLambertMaterial({ color: 0x912CEE, side: THREE.DoubleSide });var shapes = font.generateShapes("2d笔墨测试", 100, 1); var font2dGeometry = new THREE.ShapeGeometry(shapes);font2dGeometry.computeBoundingBox();var font2d = new THREE.Mesh(font2dGeometry, font2dMaterial);font2d.position.x = -0.5 (font2dGeometry.boundingBox.max.x - font2dGeometry.boundingBox.min.x);font2d.position.z += 1;scene.add(font2d);
须要把稳一点,在threejs包中供应的字体都是英笔墨体,如果想显示中文须要加入中笔墨体的json文件。
可以通过Facetype.js把中笔墨体文件转成json格式。
还有另一种更大略地添加笔墨的办法是利用精灵工具添加笔墨,不须要引入什么字体,利用Cavas直接绘制笔墨,由于精灵工具总是面向摄像头的,处理起来也方便。
代码:
let canvas = document.createElement("canvas");canvas.width =400;canvas.height = 100;let ctx = canvas.getContext("2d");ctx.fillStyle = "#ffff00";ctx.font = "Bold 100px 宋体";ctx.lineWidth = 4;ctx.fillText("精灵中笔墨体",4,104);let texture = new THREE.Texture(canvas);texture.needsUpdate = true;let material = new THREE.SpriteMaterial({map:texture});let text = new THREE.Sprite(material);text.scale.set(0.5 100, 0.25 100, 0.75 100);text.position.set(0,0,50);scene.add(text)
末了一种添加笔墨的办法是利用BMFonts (位图字体) ,可以将字形批处理为单个BufferGeometry。位图字体渲染支持自动换行、字母间距、字句调度等很多特性,有兴趣的朋友可以去Github看一下这个开源项目three-bmfont-text。