我正在学习使用“Three.js”库。我使用纹理和精灵与画布创建标签,显示信息取决于我用鼠标选择的对象。
问题在于我没有显示所有内容 在浏览器屏幕上。
您可以在此处查看问题:
代码在这里:
<html lang="en">
<head>
<title>Prueba</title>
<!-- Eliminación de la mal interpretación de signos. -->
<meta charset="utf-8">
<!-- Adaptación a la pantalla de los dispositivos móviles.-->
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<!-- Librería principal de "Three.js". -->
<script src="js/Three.js"></script>
<!-- Librería para la creación de un elemento detector. -->
<script src="js/Detector.js"></script>
<!-- Lbrería para el control de la cámara. -->
<script src="js/OrbitControls.js"></script>
<!-- Librería para el "render" ocupe toda la ventana del navegador. -->
<script src="js/THREEx.FullScreen.js"></script>
<!-- Librería para rediemnsionalizar los cambios de tamaño de la ventana del navegador. -->
<script src="js/THREEx.WindowResize.js"></script>
<!-- jQuery para proporcionar información de los objetos que hay en la escena cuando el ratón está sobre ellos. -->
<script src="js/jquery-1.9.1.js"></script>
</head>
<body>
<div id="ThreeJS" style="position: absolute; left:0px; top:0px">
</div>
<script>
// Declaración global delas variables estándar.
var container, scene, camera, renderer, controls, stats;
// Declaración global de las variables que se customizarán.
var projector, mouse = { x: 0, y: 0 }, INTERSECTED;
var sprite1;
var canvas1, context1, texture1;
// Llamada inicial de las funciones "init()" y "animate()".
init();
animate();
// Funciones:
function init() {
// Creación de la escena.
scene = new THREE.Scene();
// Creación de la cámara.
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
// Posicionamiento de la cámara.
camera.position.set(0,150,400);
camera.lookAt(scene.position);
// Creación del renderer (detección del navegador usado).
if( Detector.webgl ) {
renderer = new THREE.WebGLRenderer( {antialias:true} );
}else{
renderer = new THREE.CanvasRenderer();
}
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// Eventos de ajuste del renderer a la ventana del navegador.
THREEx.WindowResize(renderer, camera);
THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
// Control de la cámara con el ratón.
controls = new THREE.OrbitControls( camera, renderer.domElement );
// Definir las esferas (vértices o nodos).
var sphere = [];
var nummero_nodos = 48;
for (i=1;i<=nummero_nodos;i++) {
// SphereGeometry(radio esfera, ancho segemento, altura segmento)
var sphereGeometry = new THREE.SphereGeometry(8, 20, 20);
// Decidimos como se verá el plano.
var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff}); // color azul
// Creamos un objeto tipo esfera.
sphere[i] = new THREE.Mesh(sphereGeometry, sphereMaterial);
// Posicionamos la esfera en la escena.
if(i%2!=0) {
// Si la esfera es impar.
sphere[i].position.x = -50;
sphere[i].position.y = 200-50*i;
sphere[i].position.z = 0;
}else{
// Si la esfera tiene i par.
sphere[i].position.x = 50;
sphere[i].position.y = 150-50*i;
sphere[i].position.z = 0;
}
// Añadir una etiqueta a las esferas.
sphere[i].name="ESFERA "+i.toString()+", texto de relleno para mostrar el error o el fallo.";
// Añadimos la esfera a la escena.
scene.add(sphere[i]);
}
// Conocer la posición X de las esferas.
/* for(i=1;i<=nummero_nodos;i++) {
console.log(sphere[i].position.x);
} */
// Definir los tubos (relaciones).
var tube =[]
var j=1;
for(i=1;i<=nummero_nodos;i++) {
// Los vértices impares generan relaciones.
if(i%2==1) {
// Relación nodo impar-impar.
if(sphere[i-1]!=undefined && sphere[i-1]!="") {
// Definir la línea (usamos un tubo).
// Creamos el cammino que va a seguir el tubo (es decir la línea).
// Indicamos los vértices que formarán la línea.
var start = new THREE.Vector3(sphere[i].position.x,sphere[i].position.y, sphere[i].position.z);
var end = new THREE.Vector3(sphere[i-1].position.x,sphere[i-1].position.y, sphere[i-1].position.z);
// Creamos la línea.
var line = new THREE.LineCurve( start, end )
// Indicamos el número de puntos que compondrán el tubo.
var numPoints = 100;
// Decidimos como se verá el tubo.
var tubeGeometry = new THREE.TubeGeometry( line, numPoints, 2, 8, false );
var tubeMaterial = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
tube[j] = new THREE.Mesh( tubeGeometry, tubeMaterial );
tube[j].name="TUBO "+j.toString();
scene.add( tube[j] );
j+=1;
}
// Relación nodos impar-impar.
if(sphere[i+2]!=undefined && sphere[i+2]!="") {
// Definir la línea (usamos un tubo).
// Creamos el cammino que va a seguir el tubo (es decir la línea).
// Indicamos los vértices que formarán la línea.
var start = new THREE.Vector3(sphere[i].position.x, sphere[i].position.y, sphere[i].position.z);
var end = new THREE.Vector3(sphere[i+2].position.x, sphere[i+2].position.y, sphere[i+2].position.z);
// Creamos la línea.
var line = new THREE.LineCurve( start, end )
// Indicamos el número de puntos que compondrán el tubo.
var numPoints = 100;
// Decidimos como se verá el tubo.
var tubeGeometry = new THREE.TubeGeometry( line, numPoints, 2, 8, false );
var tubeMaterial = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
tube[j] = new THREE.Mesh( tubeGeometry, tubeMaterial );
tube[j].name="TUBO "+j.toString();
scene.add( tube[j] );
j+=1;
}
}
};
// Inicializar un objeto para realizar cálculos de la relación "pantalla / mundo".
projector = new THREE.Projector();
// Cuando el ratón se mueve llamamos a la función onDocumentMouseMove().
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
/////// Dibujar el texto en un elemento canvas: /////////
// Creamos el elemento tipo canvas.
canvas1 = document.createElement('canvas');
context1 = canvas1.getContext('2d');
context1.font = "Bold 20px Arial";
context1.fillStyle = "rgba(0,0,0,0.95)";
context1.fillText('Hello, world!', 0, 20);
// El contenido del elemento canvas será utilizado por un elemento del tipo textura.
texture1 = new THREE.Texture(canvas1);
texture1.needsUpdate = true;
// Creamos un elemento tipo sprite donde pondremos nuestro elemento tipo textura que contiene el texto.
var spriteMaterial = new THREE.SpriteMaterial( { map: texture1, useScreenCoordinates: true, alignment: THREE.SpriteAlignment.topLeft } );
sprite1 = new THREE.Sprite( spriteMaterial );
sprite1.scale.set(200,100,1.0);
sprite1.position.set( 50, 50, 0 );
// Añadir el sprite a la escena.
scene.add( sprite1 );
}
function onDocumentMouseMove( event ) {
// Corregimos la posición del sprite al mover el ratón.
sprite1.position.set( event.clientX, event.clientY - 20, 0 );
// Modificamos los valores de la variable mouse.
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
}
function animate() {
requestAnimationFrame( animate );
// Rellamada de las funciones.
render();
update();
}
function update() {
// Creación de una línea (ray) con origen en la posición del ratón y con dirección hacia la escena (dirección de la cámara).
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
// Creamos una matriz que contenga todos los objetos en la escena con la que la línea se cruza en su trayectoria.
var intersects = ray.intersectObjects( scene.children );
// INTERSECTED : es el objeto en la escena actualmente más cercano a la cámara e intersectado por el rayo (línea) proyectado desde la posición del ratón.
// Si hay una (o más) intersecciones.
if(intersects.length > 0) {
// Si el objeto más cercano intersectado no es el objeto de intersección actualmente almacenado.
if(intersects[ 0 ].object != INTERSECTED) {
// Restaurar el objeto de intersección anterior (si existe) a su color original.
if(INTERSECTED) {
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
}
// Almacena la referencia al objeto más cercano como objeto de intersección actual.
INTERSECTED = intersects[ 0 ].object;
// Almacena el color del objeto más cercano (para una restauración posterior).
INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
// Establece un nuevo color para el objeto más cercano.
INTERSECTED.material.color.setHex( 0xffff00 );
// Actualiza el texto, si tiene un campo "name" el objeto.
if(intersects[ 0 ].object.name) {
context1.clearRect(0,0,640,480);
var message = intersects[ 0 ].object.name;
var metrics = context1.measureText(message);
var width = metrics.width;
context1.fillStyle = "rgba(0,0,0,0.95)"; // color del borde (negro)
context1.fillRect( 0,0, width+8,20+8);
context1.fillStyle = "rgba(255,255,255,0.95)"; // color del fondo (blanco)
context1.fillRect( 2,2, width+4,20+4 );
context1.fillStyle = "rgba(0,0,0,1)"; // color del texto (negro)
context1.fillText( message, 4,20 );
texture1.needsUpdate = true;
}else{
// No existe texto ni itiqueta.
context1.clearRect(0,0,300,300);
texture1.needsUpdate = true;
}
}
// Si no hay intersección.
}else{
// Restaura el objeto de intersección anterior (si existe) a su color original.
if(INTERSECTED) {
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
}
// Elimina la referencia de objeto de intersección anterior estableciendo el objeto de intersección actual en "nada".
INTERSECTED = null;
context1.clearRect(0,0,300,300);
texture1.needsUpdate = true;
}
// Modificación de la cámara al mover el ratón.
controls.update();
}
// Renderización de la escena.
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
我尝试通过使用“fillRect()”修改画布的大小来解决问题,但它没有显示所有矩形。
我还修改了精灵的比例,但这只会扭曲字母。
最后,我试图将信息放在不同的行中,但最终只会在垂直方向发生相同的事情。
有人知道如何解决这个问题吗?有什么想法吗?
提前致谢!