javascript - 如何使三个 JS 中的 TextGeometry 跟随鼠标?
问题描述
这是我的源代码。我正在尝试使文本根据鼠标位置旋转。
// Initialization
const scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
let renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
let body = document.getElementsByTagName("body");
let pageX = 0.5;
let pageY = 0.5;
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("board").appendChild(renderer.domElement);
// Handle resize event
window.addEventListener('resize', () => {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
camera.position.z = 20;
// Create light
let directLight = new THREE.DirectionalLight('#fff', 4);
directLight.position.set(0, 7, 5);
scene.add(directLight);
var light = new THREE.AmbientLight( 0x404040 ); // soft white light
scene.add( light );
function animate (){
requestAnimationFrame( animate );
var loader = new THREE.FontLoader();
loader.load( 'https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function ( font ) {
var geometry = new THREE.TextGeometry( 'Hello three.js!', {
font: font,
size: 3,
height: 0.5,
curveSegments: 4,
bevelEnabled: true,
bevelThickness: 0.02,
bevelSize: 0.05,
bevelSegments: 3
} );
geometry.center();
var material = new THREE.MeshPhongMaterial(
{ color: '#dbe4eb', specular: '#dbe4eb' }
);
var mesh = new THREE.Mesh( geometry, material );
mesh.rotation.x = (pageY - 0.5) * 2;
mesh.rotation.y = (pageX - 0.5) * 2;
scene.add( mesh );
} );
renderer.render(scene, camera);
}
animate();
// Get mouse coordinates inside the browser
document.body.addEventListener('mousemove', (event) => {
pageX = event.pageX / window.innerWidth;
pageY = event.pageY / window.innerHeight;
});
renderer.render(scene, camera);
</script>
这是我能得到的最好的。问题是每次我移动鼠标时,它都会实例化一个新的网格并相应地旋转它,而我只需要一个网格来跟随鼠标。任何人都可以帮忙吗?提前致谢!
解决方案
正如您已经知道的那样,每一帧您都在重新加载字体并最终每次都重新创建网格。
为了解决这个问题,您需要在一些初始化函数中移动字体加载和对象创建,所以它只发生一次。
您想要保留在渲染循环中的唯一部分代码是根据鼠标移动更新文本的旋转:
mesh.rotation.x = (pageY - 0.5) * 2;
mesh.rotation.y = (pageX - 0.5) * 2;
但这会带来另一个问题。由于mesh
是在字体加载器的回调函数中定义的本地对象,因此外部无法访问它。幸运的是,three.js 提供了一个名为.name的属性,您可以使用它为对象命名。例如
var mesh = new THREE.Mesh(geometry, material);
mesh.name = "myText";
scene.add(mesh);
稍后您可以使用以下方法获取对此对象的引用:
scene.getObjectByName("myText")
这是一个例子:
var container, scene, camera, renderer, pageX, pageY;
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
pageX = 0.5;
pageY = 0.5;
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById("container").appendChild(renderer.domElement);
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
camera.position.z = 20;
let directLight = new THREE.DirectionalLight('#fff', 4);
directLight.position.set(0, 7, 5);
scene.add(directLight);
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
var loader = new THREE.FontLoader();
loader.load('https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function(font) {
var geometry = new THREE.TextGeometry('Hello three.js!', {
font: font,
size: 3,
height: 0.5,
curveSegments: 4,
bevelEnabled: true,
bevelThickness: 0.02,
bevelSize: 0.05,
bevelSegments: 3
});
geometry.center();
var material = new THREE.MeshPhongMaterial({
color: '#dbe4eb',
specular: '#dbe4eb'
});
var mesh = new THREE.Mesh(geometry, material);
mesh.name = "myText";
scene.add(mesh);
animate();
});
document.body.addEventListener('mousemove', (event) => {
pageX = event.pageX / window.innerWidth;
pageY = event.pageY / window.innerHeight;
});
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
scene.getObjectByName("myText").rotation.x = (pageY - 0.5) * 2;
scene.getObjectByName("myText").rotation.y = (pageX - 0.5) * 2;
renderer.render(scene, camera);
}
init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r120/three.min.js"></script>
<div id="container"></div>
推荐阅读
- scala - 如何构建需要多个 Scala 版本的项目?
- android - 如何在 Android 上调查墓碑崩溃数据
- javascript - 未输入国家/地区时的 Covid-19 错误消息与 API 不匹配
- html - 为什么html代码没有与css代码链接?
- python - Python在tensorflow中导入本地数据集
- vue.js - 删除 Vuetify 按钮 v-btn 中的所有边距
- c++ - 如何传递/命名函数作为参数
- r - 无法在最新版本的 Linux Mint 上安装 tidyverse
- python-3.x - Selenium python无法将键发送到第二个输入字段
- ta-lib - TA-LIB Python 金融库 - 应用新数据方法