Dragging and Clicking Objects with Controls

前端 未结 1 1786
北海茫月
北海茫月 2021-02-06 17:24

Right now I have a scene with two spheres and a point light at (0,0,0). The spheres rotate around the point using Controls, but I can\'t get the spheres to move when I attempt t

相关标签:
1条回答
  • 2021-02-06 17:52

    What you need to do is disable the controls dynamically based on whether your object is selected.

    So here are the controls I am using:

    controls = new THREE.TrackballControls(camera);
    controls.rotateSpeed = 1.0;
    controls.zoomSpeed = 1.2;
    controls.panSpeed = 0.8;
    controls.noZoom = false;
    controls.noPan = false;
    controls.staticMoving = true;
    controls.dynamicDampingFactor = 0.3;
    

    Now the controls objects in THREE.JS create mouse events that allow them to change the camera view. What we want is to disable the controls when we have an object selected, otherwise allow the controls to change the view when we drag.

    In order to do this we can declare a global variable that will act as a flag

    var killControls = false;
    

    This will be set to true when we click and cast a ray, if the ray collides with our specified object we will set killControls true.

    /** Event fired when the mouse button is pressed down */
    function onDocumentMouseDown(event) {
        event.preventDefault();
    
        /** Calculate mouse position and project vector through camera and mouse3D */
        mouse3D.x = mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse3D.y = mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
        mouse3D.z = 0.5;
        projector.unprojectVector(mouse3D, camera);
    
        var ray = new THREE.Ray(camera.position, mouse3D.subSelf(camera.position).normalize());
    
        var intersects = ray.intersectObject(maskMesh);
    
        if (intersects.length > 0) {
            SELECTED = intersects[0].object;
            var intersects = ray.intersectObject(plane);
            offset.copy(intersects[0].point).subSelf(plane.position);
            killControls = true;
        }
        else if (controls.enabled == false)
            controls.enabled = true;
    }
    
    /** This event handler is only fired after the mouse down event and
        before the mouse up event and only when the mouse moves */
    function onDocumentMouseMove(event) {
        event.preventDefault();
    
        /** Calculate mouse position and project through camera and mouse3D */
        mouse3D.x = mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse3D.y = mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
        mouse3D.z = 0.5;
        projector.unprojectVector(mouse3D, camera);
    
        var ray = new THREE.Ray(camera.position, mouse3D.subSelf(camera.position).normalize());
    
        if (SELECTED) {
            var intersects = ray.intersectObject(plane);
            SELECTED.position.copy(intersects[0].point.subSelf(offset));
            killControls = true;
            return;
        }
    
        var intersects = ray.intersectObject(maskMesh);
    
        if (intersects.length > 0) {
            if (INTERSECTED != intersects[0].object) {
                INTERSECTED = intersects[0].object;
                INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
                plane.position.copy(INTERSECTED.position);
            }
        }
        else {
            INTERSECTED = null;
        }
    }
    
    /** Removes event listeners when the mouse button is let go */
    function onDocumentMouseUp(event) {
        event.preventDefault();
        if (INTERSECTED) {
            plane.position.copy(INTERSECTED.position);
            SELECTED = null;
            killControls = false;
        }
    
    }
    
    /** Removes event listeners if the mouse runs off the renderer */
    function onDocumentMouseOut(event) {
        event.preventDefault();
        if (INTERSECTED) {
            plane.position.copy(INTERSECTED.position);
            SELECTED = null;
        }
    }
    

    And in our main animation loop, the following conditional will cause the controls to only be updated when we click and do not collide with our specified object:

    if (!killControls)
        controls.update(delta);
    else
        controls.enabled = false;
    

    EDIT: I got to looking at this today when this answer got upvoted and looking at this last block of code above I decided I think this is clearer so I changed to this in my code, of course both the below and above are equivalent:

    if (killControls) 
        controls.enabled = false;
    else 
        controls.update(delta);
    
    0 讨论(0)
提交回复
热议问题