html中sprite标签,three.js教程:使用Sprite为3D对象创建公告牌(文本标签)

HTML

导入代码模板:

import * as THREE from '//techbrood.com/threejs/build/three.module.js';

import {OrbitControls} from '//techbrood.com/threejs/examples/jsm/controls/OrbitControls.js';

function main() {

const canvas = document.querySelector('#c');

const renderer = new THREE.WebGLRenderer({canvas});

const fov = 75;

const aspect = 2; // the canvas default

const near = 0.1;

const far = 50;

const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

camera.position.set(0, 2, 5);

const controls = new OrbitControls(camera, canvas);

controls.target.set(0, 2, 0);

controls.update();

const scene = new THREE.Scene();

scene.background = new THREE.Color('white');

function addLight(position) {

const color = 0xFFFFFF;

const intensity = 1;

const light = new THREE.DirectionalLight(color, intensity);

light.position.set(...position);

scene.add(light);

scene.add(light.target);

}

addLight([-3, 1, 1]);

addLight([ 2, 1, .5]);

const bodyRadiusTop = .4;

const bodyRadiusBottom = .2;

const bodyHeight = 2;

const bodyRadialSegments = 6;

const bodyGeometry = new THREE.CylinderBufferGeometry(

bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);

const headRadius = bodyRadiusTop * 0.8;

const headLonSegments = 12;

const headLatSegments = 5;

const headGeometry = new THREE.SphereBufferGeometry(

headRadius, headLonSegments, headLatSegments);

function makeLabelCanvas(baseWidth, size, name) {

const borderSize = 2;

const ctx = document.createElement('canvas').getContext('2d');

const font = `${size}px bold sans-serif`;

ctx.font = font;

// measure how long the name will be

const textWidth = ctx.measureText(name).width;

const doubleBorderSize = borderSize * 2;

const width = baseWidth + doubleBorderSize;

const height = size + doubleBorderSize;

ctx.canvas.width = width;

ctx.canvas.height = height;

// need to set font again after resizing canvas

ctx.font = font;

ctx.textBaseline = 'middle';

ctx.textAlign = 'center';

ctx.fillStyle = 'blue';

ctx.fillRect(0, 0, width, height);

// scale to fit but don't stretch

const scaleFactor = Math.min(1, baseWidth / textWidth);

ctx.translate(width / 2, height / 2);

ctx.scale(scaleFactor, 1);

ctx.fillStyle = 'white';

ctx.fillText(name, 0, 0);

return ctx.canvas;

}

function makePerson(x, labelWidth, size, name, color) {

const canvas = makeLabelCanvas(labelWidth, size, name);

const texture = new THREE.CanvasTexture(canvas);

// because our canvas is likely not a power of 2

// in both dimensions set the filtering appropriately.

texture.minFilter = THREE.LinearFilter;

texture.wrapS = THREE.ClampToEdgeWrapping;

texture.wrapT = THREE.ClampToEdgeWrapping;

const labelMaterial = new THREE.SpriteMaterial({

map: texture,

transparent: true,

});

const bodyMaterial = new THREE.MeshPhongMaterial({

color,

flatShading: true,

});

const root = new THREE.Object3D();

root.position.x = x;

const body = new THREE.Mesh(bodyGeometry, bodyMaterial);

root.add(body);

body.position.y = bodyHeight / 2;

const head = new THREE.Mesh(headGeometry, bodyMaterial);

root.add(head);

head.position.y = bodyHeight + headRadius * 1.1;

// if units are meters then 0.01 here makes size

// of the label into centimeters.

const labelBaseScale = 0.01;

const label = new THREE.Sprite(labelMaterial);

root.add(label);

label.position.y = head.position.y + headRadius + size * labelBaseScale;

label.scale.x = canvas.width * labelBaseScale;

label.scale.y = canvas.height * labelBaseScale;

scene.add(root);

return root;

}

makePerson(-3, 150, 32, 'Purple People Eater', 'purple');

makePerson(-0, 150, 32, 'Green Machine', 'green');

makePerson(+3, 150, 32, 'Red Menace', 'red');

function resizeRendererToDisplaySize(renderer) {

const canvas = renderer.domElement;

const width = canvas.clientWidth;

const height = canvas.clientHeight;

const needResize = canvas.width !== width || canvas.height !== height;

if (needResize) {

renderer.setSize(width, height, false);

}

return needResize;

}

function render() {

if (resizeRendererToDisplaySize(renderer)) {

const canvas = renderer.domElement;

camera.aspect = canvas.clientWidth / canvas.clientHeight;

camera.updateProjectionMatrix();

}

renderer.render(scene, camera);

requestAnimationFrame(render);

}

requestAnimationFrame(render);

}

main();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值