为什么OrbitControls没有按预期工作? (three.js所)

时间:2017-11-17 18:49:50

标签: three.js

我在我的实验项目中使用THREE.OrbitControls并且与this示例非常相似。

我在顶部有不同的单选按钮,如果THREE.OrbitControls单选按钮处于活动状态,我只想启用rotate

我已将if语句中的代码替换为代码Pen示例:

    function doMouseMove(x,y,evt,prevX,prevY) {
    if (mouseAction == ROTATE) {
        var dx = x - prevX;
        world.rotateY( dx/200 );
        render();
       }

使用:

    function doMouseMove(x,y,evt,prevX,prevY) {
    if (mouseAction == ROTATE) {

    controls = new THREE.OrbitControls(camera, canvas);
    controls.rotateSpeed = 0.1;
    controls.zoomSpeed = 1;
    controls.update();

}

这很有效,但是一旦我从rotate按钮返回到drag按钮(或任何其他按钮),OrbitControls仍处于活动状态,相机随之移动被拖动/添加/删除的对象。

原始示例的情况并非如此(可以看出),所以我想知道是否必须添加其他功能来禁用OrbitControls

我试过了:

controls.reset();

但是,即使没有按下旋转单选按钮,orbitControls仍然有效!

我想补充说,当在拖动按钮(或任何其他按钮)上重新加载页面时,orbitControls未激活(按预期)。但是,一旦按下旋转按钮,无论按哪个输入,它都会在整个会话期间保持活动状态。

关于如何解决此功能的任何指示?

以下是代码的示例中的完整代码大纲(不包括带引用的HTML文件):

var canvas, scene, renderer, camera, controls;

var raycaster; // A THREE.Raycaster for user mouse input.

var ground; // A square base on which the cylinders stand.
var cylinder; // A cylinder that will be cloned to make the visible 
cylinders.

var world; 
var ROTATE = 1,
DRAG = 2,
ADD = 3,
DELETE = 4; // Possible mouse actions
var mouseAction; // currently selected mouse action
var dragItem; // the cylinder that is being dragged, during a drag operation
var intersects; //the objects intersected

var targetForDragging; // An invisible object that is used as the target for 
raycasting while

// call functions to initialise trackballcontrols
init();
 // animate();

 function init() {

canvas = document.getElementById("maincanvas");
renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: true
});

document.getElementById("mouseDrag").checked = true;
mouseAction = DRAG;
document.getElementById("mouseRotate").onchange = doChangeMouseAction;
document.getElementById("mouseDrag").onchange = doChangeMouseAction;
document.getElementById("mouseAdd").onchange = doChangeMouseAction;
document.getElementById("mouseDelete").onchange = doChangeMouseAction;
createWorld();

setUpMouseHander(canvas, doMouseDown, doMouseMove);
setUpTouchHander(canvas, doMouseDown, doMouseMove);
raycaster = new THREE.Raycaster();
render();
}

// loop that causes the renderer to draw the scene 60 times per second.
 function render() {
 renderer.render(scene, camera);
 }

 function createWorld() {

renderer.setClearColor(0x222222);
// First parameter is FOV in degrees. Second: Aspect ratio. Third/Fourth: 
 Near/Far clipping plane
camera = new THREE.PerspectiveCamera(37, canvas.width / canvas.height, 1, 
 10000);
camera.position.z = 5;
camera.position.y = 60;

/**Creating the scene */
scene = new THREE.Scene();


camera.lookAt(new THREE.Vector3(0, 1, 0));
camera.add(new THREE.PointLight(0xffffff, 0.7)); // point light at camera 
 position
scene.add(camera);
scene.add(new THREE.DirectionalLight(0xffffff, 0.5)); // light shining from 
 above.

world = new THREE.Object3D();

ground = new THREE.Mesh(
    new THREE.BoxGeometry(40, 1, 40),
    new THREE.MeshLambertMaterial({ color: "gray" })
);
ground.position.y = -0.5; // top of base lies in the plane y = -5;
world.add(ground);



targetForDragging = new THREE.Mesh(
    new THREE.BoxGeometry(1000, 0.01, 1000),
    new THREE.MeshBasicMaterial()
);
targetForDragging.material.visible = false;


cylinder = new THREE.Mesh(
    new THREE.CylinderGeometry(1, 2, 6, 16, 32),
    new THREE.MeshLambertMaterial({ color: "yellow" })
);
cylinder.position.y = 3; // places base at y = 0;

addCylinder(10, 10);
addCylinder(0, 15);
addCylinder(-15, -7);
addCylinder(-8, 5);
addCylinder(5, -12);

}

function addCylinder(x, z) {
var obj = cylinder.clone();
obj.position.x = x;
obj.position.z = z;
world.add(obj);
}

 function doMouseDown(x, y) {
//enable rotate
if (mouseAction == ROTATE) {
    return true;
}
if (mouseAction != ROTATE) {
    controls = 0;
    controls.enabled = false;
}

// Affecting drag function
if (targetForDragging.parent == world) {
    world.remove(targetForDragging); // I don't want to check for hits on 
 targetForDragging

}

var a = 2 * x / canvas.width - 1;
var b = 1 - 2 * y / canvas.height;
raycaster.setFromCamera(new THREE.Vector2(a, b), camera);
intersects = raycaster.intersectObjects(world.children); // no need for 
 recusion since all objects are top-level

if (intersects.length == 0) {
    return false;
}

var item = intersects[0];
var objectHit = item.object;

switch (mouseAction) {
    case DRAG:
        if (objectHit == ground) {
            return false;
        } else {
            dragItem = objectHit;
            world.add(targetForDragging);
            targetForDragging.position.set(0, item.point.y, 0);
            render();
            return true;
        }
    case ADD:
        if (objectHit == ground) {

            var locationX = item.point.x; // Gives the point of intersection 
 in world coords
            var locationZ = item.point.z;
            var coords = new THREE.Vector3(locationX, 0, locationZ);
            world.worldToLocal(coords); // to add cylider in correct 
   position, neew local coords for the world object
            addCylinder(coords.x, coords.z);
            render();
        }
        return false;
    default: // DELETE
        if (objectHit != ground) {
            world.remove(objectHit);
            render();
        }
        return false;
   }
 }

 //this function is used when dragging OR rotating
 function doMouseMove(x, y, evt, prevX, prevY) {

if (mouseAction == ROTATE) {
    controls = new THREE.OrbitControls(camera, canvas);
    controls.rotateSpeed = 0.1;
    controls.zoomSpeed = 1;
    controls.addEventListener('change', render, renderer.domElement);
    controls.update();

} else { // drag

    var a = 2 * x / canvas.width - 1;
    var b = 1 - 2 * y / canvas.height;
    raycaster.setFromCamera(new THREE.Vector2(a, b), camera);
    intersects = raycaster.intersectObject(targetForDragging);
    if (intersects.length == 0) {
        return;
    }
    var locationX = intersects[0].point.x;
    var locationZ = intersects[0].point.z;
    var coords = new THREE.Vector3(locationX, 0, locationZ);
    world.worldToLocal(coords);
    a = Math.min(19, Math.max(-19, coords.x)); // clamp coords to the range 
   -19 to 19, so object stays on ground
    b = Math.min(19, Math.max(-19, coords.z));
    dragItem.position.set(a, 3, b);
    render();
}
} 

  function doChangeMouseAction() {
  if (document.getElementById("mouseRotate").checked) {
      mouseAction = ROTATE;
  } else if (document.getElementById("mouseDrag").checked) {
      mouseAction = DRAG;
  } else if (document.getElementById("mouseAdd").checked) {
      mouseAction = ADD;
  } else {
      mouseAction = DELETE;
  }
 }
 window.requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback) {
    setTimeout(function() {
        callback(Date.now());
    }, 1000 / 60);
};

 function setUpMouseHander(element, mouseDownFunc, mouseDragFunc, 
 mouseUpFunc) {

if (!element || !mouseDownFunc || !(typeof mouseDownFunc == "function")) {
    throw "Illegal arguments in setUpMouseHander";
}
if (typeof element == "string") {
    element = document.getElementById(element);
}
if (!element || !element.addEventListener) {
    throw "first argument in setUpMouseHander is not a valid element";
}
var dragging = false;
var startX, startY;
var prevX, prevY;

function doMouseDown(evt) {
    if (dragging) {
        return;
    }
    var r = element.getBoundingClientRect();
    var x = evt.clientX - r.left;
    var y = evt.clientY - r.top;
    prevX = startX = x;
    prevY = startY = y;
    dragging = mouseDownFunc(x, y, evt);
    if (dragging) {
        document.addEventListener("mousemove", doMouseMove);
        document.addEventListener("mouseup", doMouseUp);
    }
}

function doMouseMove(evt) {
    if (dragging) {
        if (mouseDragFunc) {
            var r = element.getBoundingClientRect();
            var x = evt.clientX - r.left;
            var y = evt.clientY - r.top;
            mouseDragFunc(x, y, evt, prevX, prevY, startX, startY);
        }
        prevX = x;
        prevY = y;
    }
}

function doMouseUp(evt) {
    if (dragging) {
        document.removeEventListener("mousemove", doMouseMove);
        document.removeEventListener("mouseup", doMouseUp);
        if (mouseUpFunc) {
            var r = element.getBoundingClientRect();
            var x = evt.clientX - r.left;
            var y = evt.clientY - r.top;
            mouseUpFunc(x, y, evt, prevX, prevY, startX, startY);
        }
        dragging = false;
    }
}
element.addEventListener("mousedown", doMouseDown);
}

 function setUpTouchHander(element, touchStartFunc, touchMoveFunc, t 
 touchEndFunc, touchCancelFunc) {

if (!element || !touchStartFunc || !(typeof touchStartFunc == "function")) {
    throw "Illegal arguments in setUpTouchHander";
}
if (typeof element == "string") {
    element = document.getElementById(element);
}
if (!element || !element.addEventListener) {
    throw "first argument in setUpTouchHander is not a valid element";
}
var dragging = false;
var startX, startY;
var prevX, prevY;

 function doTouchStart(evt) {
    if (evt.touches.length != 1) {
        doTouchEnd(evt);
        return;
    }
    evt.preventDefault();
    if (dragging) {
        doTouchEnd();
    }
    var r = element.getBoundingClientRect();
    var x = evt.touches[0].clientX - r.left;
    var y = evt.touches[0].clientY - r.top;
    prevX = startX = x;
    prevY = startY = y;
    dragging = touchStartFunc(x, y, evt);
    if (dragging) {
        element.addEventListener("touchmove", doTouchMove);
        element.addEventListener("touchend", doTouchEnd);
        element.addEventListener("touchcancel", doTouchCancel);
    }
 }

 function doTouchMove(evt) {
    if (dragging) {
        if (evt.touches.length != 1) {
            doTouchEnd(evt);
            return;
        }
        evt.preventDefault();
        if (touchMoveFunc) {
            var r = element.getBoundingClientRect();
            var x = evt.touches[0].clientX - r.left;
            var y = evt.touches[0].clientY - r.top;
            touchMoveFunc(x, y, evt, prevX, prevY, startX, startY);
        }
        prevX = x;
        prevY = y;
    }
}

function doTouchCancel() {
    if (touchCancelFunc) {
        touchCancelFunc();
    }
}

function doTouchEnd(evt) {
    if (dragging) {
        dragging = false;
        element.removeEventListener("touchmove", doTouchMove);
        element.removeEventListener("touchend", doTouchEnd);
        element.removeEventListener("touchcancel", doTouchCancel);
        if (touchEndFunc) {
            touchEndFunc(evt, prevX, prevY, startX, startY);
        }
    }
}
element.addEventListener("touchstart", doTouchStart);
}

1 个答案:

答案 0 :(得分:1)

您可以实例化一次控件:

controls = new THREE.OrbitControls(camera, canvas);
controls.enableZoom = false;
controls.enablePan = false;
controls.enableRotate = false;

然后只需在controls.enableRotatetrue之间切换false。例如,在doChangeMouseAction()函数中。创造力取决于你。