我在我的实验项目中使用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);
}
答案 0 :(得分:1)
您可以实例化一次控件:
controls = new THREE.OrbitControls(camera, canvas);
controls.enableZoom = false;
controls.enablePan = false;
controls.enableRotate = false;
然后只需在controls.enableRotate
和true
之间切换false
。例如,在doChangeMouseAction()
函数中。创造力取决于你。