简体   繁体   English

如何用three.js拖动场景?

[英]How to drag a scene with three.js?

In the following html page I create a scene with some points, in which you can zoom comfortably by using the mouse wheel.在下面的 html 页面中,我创建了一个带有一些点的场景,您可以在其中使用鼠标滚轮舒适地缩放。

But what I want to do is to drag that scene after I have zoomed in. I want to press the left mouse button, keep it pressed and then move the mouse.但我想做的是在放大后拖动那个场景。我想按下鼠标左键,按住它然后移动鼠标。 I want the scene to move accordingly (eg by changing the x/y coordinates of the camera).我希望场景相应地移动(例如,通过更改相机的 x/y 坐标)。

I tried to create a listener to listen to clicks, but when I click somewhere I do not see any console output.我试图创建一个监听器来监听点击,但是当我点击某个地方时,我看不到任何控制台 output。

I also searched and found the suggestion to use DragControls , but this does not seem to be defined in THREE.我也搜索并找到了使用DragControls的建议,但这似乎没有在 THREE 中定义。 At least I get an error when I uncomment these lines.至少当我取消注释这些行时我得到一个错误。

So how to implement something so I can drag the whole scene (or the camera)?那么如何实现一些东西,以便我可以拖动整个场景(或相机)?

Code:代码:

<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
        <title>Test</title>
    </head>
    <body>
        <script>
            container = document.createElement('div');
            document.body.appendChild(container);
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
            camera.position.set(0, 0, 150);
            scene = new THREE.Scene();
            scene.add(camera);
            renderer = new THREE.WebGLRenderer({
                clearAlpha: 1
            });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setClearColor(0x228B22, 1);
            document.body.appendChild(renderer.domElement); 
            
            // Define a standard Circle
            circle = new THREE.CircleGeometry(1, 20);
            
            var max = 50;
            var min = -50;              
            for (var i = 0; i < 100; i++) {         
                var object = new THREE.Mesh( circle.clone(), new THREE.MeshBasicMaterial( { color: new THREE.Color('yellow'), opacity: 0.5 } ) );
                object.position.x = Math.random() * (max - min) + min;
                object.position.y = Math.random() * (max - min) + min;
                object.position.z = 0;                  
                scene.add( object );            
            }
            
            document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
            function onDocumentMouseWheel( event ) {
                var fovMAX = 100;
                var fovMIN = 1;
                camera.fov -= event.wheelDeltaY * 0.05;
                camera.fov = Math.max( Math.min( camera.fov, fovMAX ), fovMIN );
                camera.projectionMatrix = new THREE.Matrix4().makePerspective(camera.fov, window.innerWidth / window.innerHeight, camera.near, camera.far);
            }
            
            document.addEventListener( 'mouseclick', onDocumentMouseClick, false );
            function onDocumentMouseClick( event ) {
                console.log("mouseclick! " + event.offsetX + "-" + event.offsetY, );
            }
            
            animate();
            function animate() {
                requestAnimationFrame(animate);
                renderer.render(scene, camera);
            }
            
            //// undefined: 
            //var controls = new THREE.DragControls( objects, camera, renderer.domElement );            
            //controls.addEventListener( 'dragstart', function ( event ) {
            //  event.object.material.emissive.set( 0xaaaaaa );
            //} );
            //
            //controls.addEventListener( 'dragend', function ( event ) {
            //  event.object.material.emissive.set( 0x000000 );
            //} );
        </script>
    </body>
</html>

Maybe there is a better way to do this, but I found a way (see below).也许有更好的方法可以做到这一点,但我找到了一种方法(见下文)。 The trick is to have a flag that tells if the mouse button is pressed, and then you have an algorithm to determine the difference on the previous position, and move the camera accordingly.诀窍是有一个标志来判断鼠标按钮是否被按下,然后你有一个算法来确定与之前的 position 的差异,并相应地移动相机。

var mouseDown = false;
var mousePos = [0,0];
var cameraPos = 0;
        
document.addEventListener('mousedown', onMouseDown, false);
function onMouseDown( event ) {
    mouseDown = true;
    mousePos = [event.offsetX, event.offsetY];
    cameraPos = camera.position;
}
document.addEventListener('mouseup', onMouseUp, false);
function onMouseUp( event ) {
    mouseDown = false;
}
document.addEventListener('mousemove', onMouseMove, false);
function onMouseMove( event ) {
    if (mouseDown) {
        // scale factor takes into account the current FOV
        scale =  Math.tan(camera.fov/2 * Math.PI / 180)/1.5;
        dx = mousePos[0] - event.offsetX;
        dy = mousePos[1] - event.offsetY;
        x = cameraPos.x + scale*dx;
        y = cameraPos.y - scale*dy;
        camera.position.x = x;
        camera.position.y = y;
        mousePos = [event.offsetX, event.offsetY];
        cameraPos = camera.position;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM