JavaScript双击函数Three.js

JavaScript Double Click Function Three.js

本文关键字:js Three 函数 双击 JavaScript      更新时间:2024-07-05

我有一个双击功能,允许用户双击汽车模型,它显示哪些对象被相交;例如雨刮器、格栅、轮胎等,此功能会将它们显示在列表中,并显示双击与之相交的项目数。

然而,我现在正在尝试获取它,以便当点击汽车的某个部分时,例如轮胎,它会显示一段带有相关信息的段落。我可以看到,这只是一个检查相交对象的名称,然后在它与之相交时显示相关文本的情况,但每次我去做我认为正确的事情时,它都会破坏已经存在的函数,使整个事情无法运行。

我根本不是一个JavaScript或Three.js专业人士,但事实证明,要进一步推进我的功能相当困难。

有什么建议吗?我已经包含了整个双击功能,但当它检查底部附近是否有交叉点时,才需要进行更改

// On Mouse double click event function
function onDoubleClick(event) {
// Set the mouse down flag to false
mouseDown = false;
// Canvas x (left) and y (top) position
var canvasLeft = 0;
var canvasTop = 0;
// "event.clientX" is the mouse x position. "event.clientY" is the mouse y position
var tempX = event.clientX - canvasLeft;
var tempY = event.clientY - canvasTop;
// Create a normalised vector in 2d space
var vector = new THREE.Vector3((tempX / window.innerWidth) * 2 - 1, - (tempY / innerHeight) * 2 + 1, 0.5);
// Unproject a 2D point into the 3D word
// Use the camera projection matrix to transform the vector to the 3D world space
vector.unproject(camera);
// Send a ray in the direction the user has clicked from the cameras position
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
// Check if the ray has intersected with any objects and get intersections
var intersects = raycaster.intersectObjects(objects, true);
// Check if intersected with objects
if (intersects.length > 0) {
    var tempStr = "Number of items: " + intersects.length + " ";
    // List the items that were hit
    for(var i=0; i < intersects.length; i++){
        if(intersects[i].object.name != ""){
            // The mesh name set above
            tempStr += " | Name: " + intersects[i].object.name;
        } else {
            // The names inside the model
            tempStr += " | Name: " + intersects[i].object.parent.name;
        }
    }
    //Debug information
    document.getElementById("debugInfo").innerHTML = tempStr + ".<br>";
    //END
}

}

编辑:这是javascript文件的全部代码,因为更改双击函数的元素似乎会阻止页面加载。

    window.onload = init;
// declare variables    
var scene,camera,renderer, container;
var controls, guiControls, datGUI;
var grid, color;
var cube, cubeGeometry, cubeMaterial; 
var plane, planeGeometry, planeMaterial;
var skyBoxMesh, texture_placeholder;
var spotLight;
var stats;
// Handles the mouse events.
var mouseOverCanvas;
var mouseDown;
// An array of objects that can be clicked on
var objects = [];
//DAE models
var showroom ,carOld, carNew;
var daeObject;
var animations;
var kfAnimations = [];
var kfAnimationsLength = 0;
var lastFrameCurrentTime = [];
var clock = new THREE.Clock();
var mouseOverCanvas, mouseDown;
var objectsClick=[];
function init() {
    container = document.createElement( 'div' );
    document.body.appendChild( container );
    //creates empty scene
    scene = new THREE.Scene();
    //camera
    camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, .1, 500);
    camera.position.x = 40;
    camera.position.y = 40;
    camera.position.z = 40;
    camera.lookAt(scene.position);
    //renderer
    renderer = new THREE.WebGLRenderer({antialias:true});
    renderer.setClearColor(0xe6f2ff);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.shadowMapSoft = true;
    container.appendChild( renderer.domElement );
    // Add an event to set if the mouse is over our canvas
    renderer.domElement.onmouseover=function(e){ mouseOverCanvas = true; }
    renderer.domElement.onmousemove=function(e){ mouseOverCanvas = true; }
    renderer.domElement.onmouseout=function(e){ mouseOverCanvas = false; }
    renderer.domElement.onmousedown=function(e){ mouseDown = true; }
    renderer.domElement.onmouseup=function(e){ mouseDown = false; }
    // Double Click Event. Set a function called "onDoubleClick"
    renderer.domElement.ondblclick=onDoubleClick;
     // stats
    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.left = '0px';
    stats.domElement.style.top = '0px';
    container.appendChild( stats.domElement );
     //adds controls
     controls = new THREE.OrbitControls(camera, renderer.domElement);
     controls.addEventListener('change', render);
     var ambient = new THREE.AmbientLight( 0xadad85 );
     scene.add( ambient ); 
     //---------- creates grid ---------------
     grid = new THREE.GridHelper(50,5);
     color= new THREE.Color("rgb(255,0,0)");
     grid.setColors( 0x000000);
     scene.add(grid);
     //----------- creates cube --------------
     cubeGeometry = new THREE.BoxGeometry(5,5,5);
     cubeMaterial = new THREE.MeshPhongMaterial({color: 0xff3300});
     cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
     cube.position.x = 0;
     cube.position.y = 6;
     cube.position.z = 2.5;
     cube.castShadow = true;
     scene.add(cube);
     //----------- creates plane ---------------
     planeGeomenty= new THREE.PlaneGeometry(100,100,100);
     planeMaterial = new THREE.MeshLambertMaterial({color: 0x00cc00});
     plane = new THREE.Mesh(planeGeomenty, planeMaterial);
     //position the add objects to the scene
     plane.rotation.x = -.5*Math.PI;
     plane.receiveShadow = true;
     scene.add(plane);
    //------------- skyBox --------------
    texture_placeholder = document.createElement('canvas');
    texture_placeholder.width = 128;
    texture_placeholder.height = 128;
    var context = texture_placeholder.getContext('2d');
    context.fillStyle = 'rgb(200,200, 200)';
    context.fillRect(0, 0,texture_placeholder.width, texture_placeholder.height);
    var materials = [
         loadTexture('images/skybox/posX.jpg'),
         loadTexture('images/skybox/negX.jpg'),
         loadTexture('images/skybox/posY.jpg'),
         loadTexture('images/skybox/negY.jpg'),
         loadTexture('images/skybox/posZ.jpg'),
         loadTexture('images/skybox/negZ.jpg')
         ];
    skyBoxMesh = new THREE.Mesh(new THREE.BoxGeometry(500,500,500,7,7,7),
                                new THREE.MeshFaceMaterial(materials));
    skyBoxMesh.scale.x = -1;
    scene.add(skyBoxMesh);
    //---------- loads collada files  -----------
    loadCollada();
    daeObject = cube; 
    // initialise datGUI controls values
    guiControls = new function() {
        this.rotationY = 0.0;
        this.positionX = 0.0;
        this.positionY = 0.0;
        this.positionZ = -10;
        this.lightX = 20;
        this.lightY = 35;
        this.lightZ = 40;
        this.intensity = 1;
        this.distance = 0;
        this.angle = 1.570;
        this.target = cube;
    }
    //add spotLight with starting parameters
    spotLight = new THREE.SpotLight(0xffffff);
    spotLight.castShadow = true;
    spotLight.position.set(20,35,40);
    spotLight.intensity = guiControls.intensity;
    spotLight.distance = guiControls.distance;
    spotLight.angle = guiControls.angle;
    scene.add(spotLight);
    //adds controls on the scene
    datGUI = new dat.GUI();
   // datGUI.add(guiControls, 'positionZ', 0, 1);
    datGUI.add(guiControls, 'positionZ', -10, 25, 0.5). name("Move the car");
    datGUI.add(guiControls, 'rotationY', 0, 1).name('Rotate the car');
    datGUI.add(guiControls, 'lightX', -60, 180);
    datGUI.add(guiControls, 'lightY', 0, 180);
    datGUI.add(guiControls, 'lightZ', -60, 180);
    datGUI.add(guiControls, 'target',[ 'cube','Modern Mini', 'Classic Mini']).onChange(function() {
        if(guiControls.target == 'cube'){
            spotLight.target = cube;
            daeObject = cube;
        } 
         else if(guiControls.target == 'Classic Mini'){
            spotLight.target = carOld;
            daeObject = carOld;
        }
        else if(guiControls.target = 'Modern Mini'){
            spotLight.target = carNew;
            daeObject = carNew;
        }           
    });
    datGUI.add(guiControls, 'intensity', 0.01, 5).onChange(function (value){
        spotLight.intensity = value;
    });
    datGUI.add(guiControls, 'distance', 0, 1000).onChange(function (value){
        spotLight.distance = value;
    });
    datGUI.add(guiControls, 'angle', 0.001, 1.570).onChange(function (value){
        spotLight.angle = value;
    });
    datGUI.close();
    container.appendChild(renderer.domElement);
    window.addEventListener( 'resize', onWindowResize, false );
}     
//------------------------- END INIT() ----------------------------
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
}
function loadCollada() {
    //--- Loads the Classic Mini ---
    colladaLoader = new THREE.ColladaLoader();
    colladaLoader.options.convertUpAxis = true;
    colladaLoader.load( 'dae_files/ClassicMini.dae', function ( collada ) {
        carOld = collada.scene; // stores dae file to a global variable
        carOld.position.set( 14.5, 1.8, -10 );         
        carOld.scale.set( 0.04, 0.04, 0.04 );           
        carOld.traverse(function (child) {
            child.castShadow = true;
            child.receiveShadow = true;
           });
        carOld.updateMatrix();
        carOld.name = "Classic";
        scene.add( carOld );
        objects.push( carOld );
    } );
    //--- loads Modern Mini ---
    colladaLoader = new THREE.ColladaLoader();
    colladaLoader.options.convertUpAxis = true;
    colladaLoader.load( 'dae_files/ModernMini.dae', function ( collada ) {
        carNew = collada.scene;
        carNew.position.set( -14.5, 6.3, -10 ); 
        carNew.scale.set( 0.06, 0.06, 0.06 );   
        // creates shadow   
        carNew.traverse(function (child) {
        child.castShadow = true;
        child.receiveShadow = true;
        });
        carNew.updateMatrix();
        carNew.name = "Modern";
        scene.add( carNew );
        objects.push( carNew );
    } );
    //--- loads the Showroom ---    
    colladaLoader = new THREE.ColladaLoader();
    colladaLoader.options.convertUpAxis = true; 
    colladaLoader.load( 'dae_files/roomAnim2.dae', function  collada( collada ) {
        showroom = collada.scene;
        animations = collada.animations;
        kfAnimationsLength = animations.length;
        // Initialise last frame current time.
        for ( var i = 0; i < kfAnimationsLength; i++ ) {
            lastFrameCurrentTime[i] = 0;
        }
        // Get all the key frame animations.
        for ( var i = 0; i < kfAnimationsLength; i++ ) {
            var anim = animations[ i ];
            var keyFrameAnim = new THREE.KeyFrameAnimation( anim );
            keyFrameAnim.timeScale = 1;
            keyFrameAnim.loop = false;
            kfAnimations.push( keyFrameAnim );
            anim = kfAnimations[i];
            anim.play();
        }
        showroom.position.set(0, 0, -20);
        showroom.scale.set(0.06, 0.06, 0.06);
        showroom.traverse(function (child) {
            child.castShadow = true;
            child.receiveShadow = true;
           });
        showroom.updateMatrix();
        scene.add( showroom );
        animate();
    } );    
}
// On Mouse double click event function
function onDoubleClick(event) {
    // Set the mouse down flag to false
    mouseDown = false;
    // Canvas x (left) and y (top) position
    var canvasLeft = 0;
    var canvasTop = 0;
    // "event.clientX" is the mouse x position. "event.clientY" is the mouse y position
    var tempX = event.clientX - canvasLeft;
    var tempY = event.clientY - canvasTop;
    // Create a normalised vector in 2d space
    var vector = new THREE.Vector3((tempX / window.innerWidth) * 2 - 1, - (tempY / innerHeight) * 2 + 1, 0.5);
    // Unproject a 2D point into the 3D word
    // Use the camera projection matrix to transform the vector to the 3D world space
    vector.unproject(camera);
    // Send a ray in the direction the user has clicked from the cameras position
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
    // Check if the ray has intersected with any objects and get intersections
    var intersects = raycaster.intersectObjects(objects, true);
    // Check if intersected with objects
    if (intersects.length > 0) {
        var tempStr = "Number of items: " + intersects.length + " ";
        // List the items that were hit
        for(var i=0; i < intersects.length; i++){
            if(intersects[i].object.name != ""){
                // The mesh name set above
                tempStr += " | Name: " + intersects[i].object.name;
            } else {
                // The names inside the model
                tempStr += " | Name: " + intersects[i].object.parent.name;
            }
        }
        //Debug information
        document.getElementById("debugInfo").innerHTML = tempStr + ".<br>";
        //END
    }
}
function loopAnimations(){
    // Loop through all animations
    for ( var i = 0; i < kfAnimationsLength; i++ ) {
        // Check if the animation is player and not paused.
        if(kfAnimations[i].isPlaying && !kfAnimations[i].isPaused){
            if(kfAnimations[i].currentTime == lastFrameCurrentTime[i]) {
                kfAnimations[i].stop();
                //kfAnimations[i].play();
                lastFrameCurrentTime[i] = 0;
            }
        }
    }
}
function play_pauseAnim() {
    //checks is there animation and is it paused    
    if(kfAnimationsLength > 0) {
        if(kfAnimations[0].isPlaying) {
            for(i = 0; i < kfAnimationsLength; i++){
                kfAnimations[i].stop();
            }
        }else {
            for(i = 0; i < kfAnimationsLength; i++) {
                lastFrameCurrentTime[i] = 0;
                //kfAnimations[i].play(kfAnimations[i].currentTime);
                kfAnimations[i].play(0);
            }
        }
    }   
}
function checkTime(){
    if(kfAnimationsLength > 0) {
        if(kfAnimations[0].isPlaying) {
            if(kfAnimations[0].currentTime > 3){
                play_pauseAnim();
            }
        }
    }
}
// create a render loop to draw the scene 60 times per second
function render() {
    //checkTime();
    daeObject.rotation.y += guiControls.rotationY;
    //if (daeObject.position.z < 25) {
    daeObject.position.z = guiControls.positionZ;   
    //}
    spotLight.rotation.x += guiControls.rotationX;
    spotLight.rotation.y += guiControls.rotationY;
    spotLight.rotation.z += guiControls.rotationZ;
    stats.update(); 
}
function animate () {
    var deltaTime = clock.getDelta();
    for ( var i = 0; i < kfAnimationsLength; i++ ) {
        // Get a key frame animation.
        var anim = kfAnimations[i];
        anim.update( deltaTime );
    }
    loopAnimations();
    requestAnimationFrame(animate);
        // Update last frame current time.
    for ( var i = 0; i < kfAnimationsLength; i++ ) {
        lastFrameCurrentTime[i] = kfAnimations[i].currentTime;
    }
    render();   
    renderer.render(scene, camera);
}
// Loads skybox texture
function loadTexture(path) {
    var texture = new THREE.Texture(texture_placeholder);
    var material = new THREE.MeshBasicMaterial({
                map: texture,
                overdraw: 0.5
    });
    var image = new Image();
    image.onload = function() {
        texture.image = this;
        texture.needsUpdate = true;
    };
    image.src = path;
    return material;    
}

Macast,

请检查您是否没有忘记代码:

var objets = [];
var raycaster = new THREE.Raycaster();

对于汽车的每个部分,这条线:

objects.push( mesh );

例如:

var geometry = new THREE.RingGeometry( 1, 5, 32 );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, side: THREE.DoubleSide } );
var simpleTire = new THREE.Mesh( geometry, material );
simpleTire.name = 'tire';
objects.push( simpleTire );
scene.add( simpleTire );

那么,很简单:

if ( intersects.length > 0 ) {
    switch(intersects[0].object.name){
        case 'tire':
            console.log('A pretty red tire');
        break;
        case 'motor':
            console.log('An electric motor');
        break;
       }
 }