【问题标题】:How to drag a scene with three.js?如何用three.js拖动场景?
【发布时间】:2020-08-23 16:27:54
【问题描述】:

在下面的 html 页面中,我创建了一个带有一些点的场景,您可以在其中使用鼠标滚轮舒适地缩放。

但我想做的是在放大后拖动那个场景。我想按下鼠标左键,按住它然后移动鼠标。我希望场景相应地移动(例如,通过更改相机的 x/y 坐标)。

我尝试创建一个监听器来监听点击,但是当我点击某个地方时,我看不到任何控制台输出。

我也搜了一下,找到了使用DragControls的建议,但是这似乎没有在THREE中定义。至少当我取消注释这些行时我得到一个错误。

那么如何实现一些东西,以便我可以拖动整个场景(或相机)?

代码:

<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>

【问题讨论】:

  • 您正在使用 4 年前的 three.js 的修订版。更新到当前版本。 OrbitControls 有你描述的功能。

标签: javascript three.js


【解决方案1】:

也许有更好的方法可以做到这一点,但我找到了一种方法(见下文)。诀窍是有一个标志来判断是否按下了鼠标按钮,然后你有一个算法来确定先前位置的差异,并相应地移动相机。

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;
    }
}

【讨论】:

  • 我知道这是一篇旧帖子,但您还记得您是如何设计数学来确定比例的吗?我在threejs中做了类似的事情,但我仍然不确定确定它的最佳方法是什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-02
  • 2013-01-28
  • 2015-08-11
  • 2012-11-01
  • 2014-12-28
  • 1970-01-01
  • 2016-09-07
相关资源
最近更新 更多