星系模拟:更改点的颜色并在鼠标悬停时显示文本 [英] Galaxies simulation: Change color of a point and display text on mouseover
问题描述
我正在尝试创建最近的星系4673位置的模拟.
>星系是点.
我想在鼠标悬停时给一个点上色并加载星系的名称.
我花了很多天试图实现它.我可以更改颜色,也可以进行基本的射线投射,但是,我无法单独对每个点进行射线投射/着色.如当前版本所示,所有这些点都进行了射线广播和着色.
我该怎么做才能更正此问题?非常感谢您的时间和耐心与初学者.
可在此处获得完整代码.
相关代码如下:
window.addEventListener( "mousemove", onDocumentMouseMove, false );
var selectedObject = null;
function onDocumentMouseMove( event ) {
event.preventDefault();
if ( selectedObject ) {
selectedObject.material.color.set( '#fff' );
selectedObject = null;
}
var intersects = getIntersects( event.layerX, event.layerY );
if ( intersects.length > 0 ) {
var res = intersects.filter( function ( res ) {
return res && res.object;
} )[ 0 ];
if ( res && res.object ) {
selectedObject = res.object;
selectedObject.material.color.set( '#69f' );
}
}
}
var raycaster = new THREE.Raycaster();
var mouseVector = new THREE.Vector3();
function getIntersects( x, y ) {
x = ( x / window.innerWidth ) * 2 - 1;
y = - ( y / window.innerHeight ) * 2 + 1;
mouseVector.set( x, y, 0.5 );
raycaster.setFromCamera( mouseVector, camera );
return raycaster.intersectObject( dots, true );
}
首先要做的是将raycaster.params.Points.threshold
设置为等于点的大小.这样一来,当用户将鼠标悬停在任意点上时,所有点的颜色都会改变:
(为了方便悬停,我增加了您的磅数):
<html>
<head>
<meta charset="UTF-8">
<style>
body { margin: 0; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/f32e6f14046b5affabe35a0f42f0cad7b5f2470e/examples/js/controls/TrackballControls.js"></script>
</head>
<body>
<script>
// Create an empty scene
var scene = new THREE.Scene();
// Create a basic perspective camera
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.x = 200;
// Create a renderer with Antialiasing
var renderer = new THREE.WebGLRenderer({antialias:true});
// Configure renderer clear color
renderer.setClearColor("#000000");
// Configure renderer size
renderer.setSize( window.innerWidth, window.innerHeight );
// Append Renderer to DOM
document.body.appendChild( renderer.domElement );
//Add Milky Way
var dotGeometry = new THREE.Geometry();
dotGeometry.vertices.push(new THREE.Vector3( 0, 0, 0));
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "https://rawcdn.githack.com/RiteshSingh/galaxies/9e6a4e54b37647e5a9a1d6f16c017769533fe258/galaxydata.txt", false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
var data = allText.split("\n");
for (var i = 0; i < 4672; i++) {
var parts = data[i].split("\t");
var D = parts[0];
var glon = parts[1]*3.1416/180;
var glat = parts[2]*3.1416/180;
var z = D*Math.sin(glat);
var xy = D*Math.cos(glat);
var x = xy*Math.cos(glon);
var y = xy*Math.sin(glon);
dotGeometry.vertices.push(new THREE.Vector3( x, y, z));
}
}
}
}
rawFile.send(null);
var size = 0.32;
var dotMaterial = new THREE.PointsMaterial( { size: size } );
var dots = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dots );
var controls = new THREE.TrackballControls( camera, renderer.domElement );
// Render Loop
var render = function () {
requestAnimationFrame( render );
controls.update();
// Render the scene
renderer.render(scene, camera);
};
render();
window.addEventListener( "mousemove", onDocumentMouseMove, false );
var selectedObject = null;
function onDocumentMouseMove( event ) {
event.preventDefault();
if ( selectedObject ) {
selectedObject.material.color.set( '#fff' );
selectedObject = null;
}
var intersects = getIntersects( event.layerX, event.layerY );
if ( intersects.length > 0 ) {
var res = intersects.filter( function ( res ) {
return res && res.object;
} )[ 0 ];
if ( res && res.object ) {
selectedObject = res.object;
selectedObject.material.color.set( '#69f' );
}
}
}
var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = size;
var mouseVector = new THREE.Vector3();
function getIntersects( x, y ) {
x = ( x / window.innerWidth ) * 2 - 1;
y = - ( y / window.innerHeight ) * 2 + 1;
mouseVector.set( x, y, 0.5 );
raycaster.setFromCamera( mouseVector, camera );
return raycaster.intersectObject( dots, true );
}
</script>
</body>
</html>
然后,您只需要使其变为仅悬停的点即可更改颜色:
<html>
<head>
<meta charset="UTF-8">
<style>
body { margin: 0; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/f32e6f14046b5affabe35a0f42f0cad7b5f2470e/examples/js/controls/TrackballControls.js"></script></script>
</head>
<body>
<script>
// Create an empty scene
var scene = new THREE.Scene();
// Create a basic perspective camera
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.x = 200;
// Create a renderer with Antialiasing
var renderer = new THREE.WebGLRenderer({antialias:true});
// Configure renderer clear color
renderer.setClearColor("#000000");
// Configure renderer size
renderer.setSize( window.innerWidth, window.innerHeight );
// Append Renderer to DOM
document.body.appendChild( renderer.domElement );
//Add Milky Way
var dotGeometry = new THREE.Geometry();
dotGeometry.vertices.push();
var colors = [];
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "https://rawcdn.githack.com/RiteshSingh/galaxies/9e6a4e54b37647e5a9a1d6f16c017769533fe258/galaxydata.txt", false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
var data = allText.split("\n");
for (var i = 0; i < 4672; i++) {
var parts = data[i].split("\t");
var D = parts[0];
var glon = parts[1]*3.1416/180;
var glat = parts[2]*3.1416/180;
var z = D*Math.sin(glat);
var xy = D*Math.cos(glat);
var x = xy*Math.cos(glon);
var y = xy*Math.sin(glon);
dotGeometry.vertices.push(new THREE.Vector3( x, y, z));
colors.push(new THREE.Color(0xFF0000));
}
}
}
}
rawFile.send(null);
dotGeometry.colors = colors;
var size = 0.32;
var dotMaterial = new THREE.PointsMaterial({
size: size,
vertexColors: THREE.VertexColors,
});
var dots = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dots );
var controls = new THREE.TrackballControls( camera, renderer.domElement );
// Render Loop
var render = function () {
requestAnimationFrame( render );
controls.update();
// Render the scene
renderer.render(scene, camera);
};
render();
window.addEventListener( "mousemove", onDocumentMouseMove, false );
var selectedObject = null;
function onDocumentMouseMove( event ) {
event.preventDefault();
if ( selectedObject ) {
selectedObject.material.color.set( '#fff' );
selectedObject = null;
}
var intersects = getIntersects( event.layerX, event.layerY );
if ( intersects.length > 0 ) {
var idx = intersects[0].index;
dots.geometry.colors[idx] = new THREE.Color(0xFFFFFF);
dots.geometry.colorsNeedUpdate = true;
console.log(idx)
}
}
var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = size;
var mouseVector = new THREE.Vector3();
function getIntersects( x, y ) {
x = ( x / window.innerWidth ) * 2 - 1;
y = - ( y / window.innerHeight ) * 2 + 1;
mouseVector.set( x, y, 0.5 );
raycaster.setFromCamera( mouseVector, camera );
return raycaster.intersectObject( dots, true );
}
</script>
</body>
</html>
用户将鼠标悬停在这些点上时,您会看到这些点变成白色.
我将其作为教学法练习,让您确定在鼠标退出给定点后如何将这些点变回红色:)
I am trying to create a simulation of positions of 4673 of the nearest galaxies.
The galaxies are points.
I want to color a point on mouseover and load the name of the galaxy.
I have spent many days trying to achieve it. I am able to change color, as well as do basic raycasting, however, I am unable to separately raycast/color individual point. All the points are raycasted and colored as a group as seen in the current version.
What should I do to correct this? Thank you so much for your time and patience with a beginner.
Complete code is available here.
Relevant code is included below:
window.addEventListener( "mousemove", onDocumentMouseMove, false );
var selectedObject = null;
function onDocumentMouseMove( event ) {
event.preventDefault();
if ( selectedObject ) {
selectedObject.material.color.set( '#fff' );
selectedObject = null;
}
var intersects = getIntersects( event.layerX, event.layerY );
if ( intersects.length > 0 ) {
var res = intersects.filter( function ( res ) {
return res && res.object;
} )[ 0 ];
if ( res && res.object ) {
selectedObject = res.object;
selectedObject.material.color.set( '#69f' );
}
}
}
var raycaster = new THREE.Raycaster();
var mouseVector = new THREE.Vector3();
function getIntersects( x, y ) {
x = ( x / window.innerWidth ) * 2 - 1;
y = - ( y / window.innerHeight ) * 2 + 1;
mouseVector.set( x, y, 0.5 );
raycaster.setFromCamera( mouseVector, camera );
return raycaster.intersectObject( dots, true );
}
First thing to do is to set raycaster.params.Points.threshold
equal to the size of your points. This makes it so that the colors of all points change when a user hovers over any point:
(I increased your point size for ease of hovering):
<html>
<head>
<meta charset="UTF-8">
<style>
body { margin: 0; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/f32e6f14046b5affabe35a0f42f0cad7b5f2470e/examples/js/controls/TrackballControls.js"></script>
</head>
<body>
<script>
// Create an empty scene
var scene = new THREE.Scene();
// Create a basic perspective camera
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.x = 200;
// Create a renderer with Antialiasing
var renderer = new THREE.WebGLRenderer({antialias:true});
// Configure renderer clear color
renderer.setClearColor("#000000");
// Configure renderer size
renderer.setSize( window.innerWidth, window.innerHeight );
// Append Renderer to DOM
document.body.appendChild( renderer.domElement );
//Add Milky Way
var dotGeometry = new THREE.Geometry();
dotGeometry.vertices.push(new THREE.Vector3( 0, 0, 0));
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "https://rawcdn.githack.com/RiteshSingh/galaxies/9e6a4e54b37647e5a9a1d6f16c017769533fe258/galaxydata.txt", false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
var data = allText.split("\n");
for (var i = 0; i < 4672; i++) {
var parts = data[i].split("\t");
var D = parts[0];
var glon = parts[1]*3.1416/180;
var glat = parts[2]*3.1416/180;
var z = D*Math.sin(glat);
var xy = D*Math.cos(glat);
var x = xy*Math.cos(glon);
var y = xy*Math.sin(glon);
dotGeometry.vertices.push(new THREE.Vector3( x, y, z));
}
}
}
}
rawFile.send(null);
var size = 0.32;
var dotMaterial = new THREE.PointsMaterial( { size: size } );
var dots = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dots );
var controls = new THREE.TrackballControls( camera, renderer.domElement );
// Render Loop
var render = function () {
requestAnimationFrame( render );
controls.update();
// Render the scene
renderer.render(scene, camera);
};
render();
window.addEventListener( "mousemove", onDocumentMouseMove, false );
var selectedObject = null;
function onDocumentMouseMove( event ) {
event.preventDefault();
if ( selectedObject ) {
selectedObject.material.color.set( '#fff' );
selectedObject = null;
}
var intersects = getIntersects( event.layerX, event.layerY );
if ( intersects.length > 0 ) {
var res = intersects.filter( function ( res ) {
return res && res.object;
} )[ 0 ];
if ( res && res.object ) {
selectedObject = res.object;
selectedObject.material.color.set( '#69f' );
}
}
}
var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = size;
var mouseVector = new THREE.Vector3();
function getIntersects( x, y ) {
x = ( x / window.innerWidth ) * 2 - 1;
y = - ( y / window.innerHeight ) * 2 + 1;
mouseVector.set( x, y, 0.5 );
raycaster.setFromCamera( mouseVector, camera );
return raycaster.intersectObject( dots, true );
}
</script>
</body>
</html>
Then you just need to make it so that only the hovered point changes color:
<html>
<head>
<meta charset="UTF-8">
<style>
body { margin: 0; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/f32e6f14046b5affabe35a0f42f0cad7b5f2470e/examples/js/controls/TrackballControls.js"></script></script>
</head>
<body>
<script>
// Create an empty scene
var scene = new THREE.Scene();
// Create a basic perspective camera
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.x = 200;
// Create a renderer with Antialiasing
var renderer = new THREE.WebGLRenderer({antialias:true});
// Configure renderer clear color
renderer.setClearColor("#000000");
// Configure renderer size
renderer.setSize( window.innerWidth, window.innerHeight );
// Append Renderer to DOM
document.body.appendChild( renderer.domElement );
//Add Milky Way
var dotGeometry = new THREE.Geometry();
dotGeometry.vertices.push();
var colors = [];
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "https://rawcdn.githack.com/RiteshSingh/galaxies/9e6a4e54b37647e5a9a1d6f16c017769533fe258/galaxydata.txt", false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
var data = allText.split("\n");
for (var i = 0; i < 4672; i++) {
var parts = data[i].split("\t");
var D = parts[0];
var glon = parts[1]*3.1416/180;
var glat = parts[2]*3.1416/180;
var z = D*Math.sin(glat);
var xy = D*Math.cos(glat);
var x = xy*Math.cos(glon);
var y = xy*Math.sin(glon);
dotGeometry.vertices.push(new THREE.Vector3( x, y, z));
colors.push(new THREE.Color(0xFF0000));
}
}
}
}
rawFile.send(null);
dotGeometry.colors = colors;
var size = 0.32;
var dotMaterial = new THREE.PointsMaterial({
size: size,
vertexColors: THREE.VertexColors,
});
var dots = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dots );
var controls = new THREE.TrackballControls( camera, renderer.domElement );
// Render Loop
var render = function () {
requestAnimationFrame( render );
controls.update();
// Render the scene
renderer.render(scene, camera);
};
render();
window.addEventListener( "mousemove", onDocumentMouseMove, false );
var selectedObject = null;
function onDocumentMouseMove( event ) {
event.preventDefault();
if ( selectedObject ) {
selectedObject.material.color.set( '#fff' );
selectedObject = null;
}
var intersects = getIntersects( event.layerX, event.layerY );
if ( intersects.length > 0 ) {
var idx = intersects[0].index;
dots.geometry.colors[idx] = new THREE.Color(0xFFFFFF);
dots.geometry.colorsNeedUpdate = true;
console.log(idx)
}
}
var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = size;
var mouseVector = new THREE.Vector3();
function getIntersects( x, y ) {
x = ( x / window.innerWidth ) * 2 - 1;
y = - ( y / window.innerHeight ) * 2 + 1;
mouseVector.set( x, y, 0.5 );
raycaster.setFromCamera( mouseVector, camera );
return raycaster.intersectObject( dots, true );
}
</script>
</body>
</html>
You'll see the points turn white after the user mouses over them.
I'll leave it as a pedagogical exercise for you to determine how to turn the points back to red after the mouse exits a given point :)
这篇关于星系模拟:更改点的颜色并在鼠标悬停时显示文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!