【问题标题】:How to use OrbitControls in Three.js Editor project如何在 Three.js 编辑器项目中使用 OrbitControls
【发布时间】:2022-03-24 18:31:13
【问题描述】:

使用Three.js Editor,我导出了一个带有简单场景(两个框)的项目。一切正常——我从我的 PerspectiveCamera 中看到了我添加的两个框。我想用鼠标滚轮控制我的相机视图。这是 index.html 中的脚本:

    <script type="module">
        import * as THREE from './js/three.module.js';
        import { APP } from './js/app.js';
        import {OrbitControls} from './js/OrbitControls.js';  //  I added this part.

        // OrbitControls here?

        var loader = new THREE.FileLoader();
        loader.load( 'app.json', function ( text ) {
            var player = new APP.Player( THREE );
            player.load( JSON.parse( text ) );
            player.setSize( window.innerWidth, window.innerHeight );
            player.play();
            document.body.appendChild( player.dom );
            window.addEventListener( 'resize', function () {
                player.setSize( window.innerWidth, window.innerHeight );
            } );
        } );
    </script>

如何使用 OrbitControls 来实现这一点?我尝试过的所有事情(基于类似的线程)都会导致未定义事物的错误(例如“相机”或“控件”,具体取决于我放置它的位置)。

或者(甚至更理想),有没有办法在 Three.js 编辑器本身中定义我想要的相机行为?那就太棒了!


编辑

感谢@Mugen87 的原始答案(基本上,如果不编辑 app.js,这是不可能的),现在是问题的状态。我从我的 index.html(上图)中删除了 OrbitControls 导入并将其添加到我的 app.js 中。所以我的 app.js 目前看起来像这样:

import {OrbitControls} from './OrbitControls.js';
var APP = {
  Player: function ( THREE ) {
    window.THREE = THREE; // FIX for editor scripts (they require THREE in global namespace)
    var loader = new THREE.ObjectLoader();
    var camera, scene, renderer;
    var events = {};
    var dom = document.createElement( 'div' );
    dom.className = "threejs-app";
    this.dom = dom;
    this.width = 500;
    this.height = 500;
    this.load = function ( json ) {
        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.outputEncoding = THREE.sRGBEncoding;
        renderer.setClearColor( 0x000000 );
        renderer.setPixelRatio( window.devicePixelRatio );
        var project = json.project;
        if ( project.shadows ) renderer.shadowMap.enabled = true;
        if ( project.vr ) renderer.xr.enabled = true;
        dom.appendChild( renderer.domElement );
        this.setScene( loader.parse( json.scene ) );
        this.setCamera( loader.parse( json.camera ) );
        events = {
            init: [],
            start: [],
            stop: [],
            keydown: [],
            keyup: [],
            mousedown: [],
            mouseup: [],
            mousemove: [],
            touchstart: [],
            touchend: [],
            touchmove: [],
            update: []
        };
        var scriptWrapParams = 'player,renderer,scene,camera';
        var scriptWrapResultObj = {};
        for ( var eventKey in events ) {
            scriptWrapParams += ',' + eventKey;
            scriptWrapResultObj[ eventKey ] = eventKey;
        }
        var scriptWrapResult = JSON.stringify( scriptWrapResultObj ).replace( /\"/g, '' );
        for ( var uuid in json.scripts ) {
            var object = scene.getObjectByProperty( 'uuid', uuid, true );
            if ( object === undefined ) {
                console.warn( 'APP.Player: Script without object.', uuid );
                continue;
            }
            var scripts = json.scripts[ uuid ];
            for ( var i = 0; i < scripts.length; i ++ ) {
                var script = scripts[ i ];
                var functions = ( new Function( scriptWrapParams, script.source + '\nreturn ' + scriptWrapResult + ';' ).bind( object ) )( this, renderer, scene, camera );
                for ( var name in functions ) {
                    if ( functions[ name ] === undefined ) continue;
                    if ( events[ name ] === undefined ) {
                        console.warn( 'APP.Player: Event type not supported (', name, ')' );
                        continue;
                    }
                    events[ name ].push( functions[ name ].bind( object ) );
                }
            }
        }
        dispatch( events.init, arguments );
        };
        this.setCamera = function ( value ) {
            camera = value;
            camera.aspect = this.width / this.height;
            camera.updateProjectionMatrix();
        };
        this.setScene = function ( value ) {
            scene = value;
        };
        this.setSize = function ( width, height ) {
            this.width = width;
            this.height = height;
            if ( camera ) {
                camera.aspect = this.width / this.height;
                camera.updateProjectionMatrix();
            }
            if ( renderer ) {
                renderer.setSize( width, height );
            }
        };
        function dispatch( array, event ) {
            for ( var i = 0, l = array.length; i < l; i ++ ) {
                array[ i ]( event );
            }
        }
        var time, prevTime;
        function animate() {
            time = performance.now();
            try {
                dispatch( events.update, { time: time, delta: time - prevTime } );
            } catch ( e ) {
                console.error( ( e.message || e ), ( e.stack || "" ) );
            }
            renderer.render( scene, camera );
            prevTime = time;
        }
        this.play = function () {
            prevTime = performance.now();
            document.addEventListener( 'keydown', onDocumentKeyDown );
            document.addEventListener( 'keyup', onDocumentKeyUp );
            document.addEventListener( 'mousedown', onDocumentMouseDown );
            document.addEventListener( 'mouseup', onDocumentMouseUp );
            document.addEventListener( 'mousemove', onDocumentMouseMove );
            document.addEventListener( 'touchstart', onDocumentTouchStart );
            document.addEventListener( 'touchend', onDocumentTouchEnd );
            document.addEventListener( 'touchmove', onDocumentTouchMove );
            dispatch( events.start, arguments );
            renderer.setAnimationLoop( animate );
        };
        this.stop = function () {
            document.removeEventListener( 'keydown', onDocumentKeyDown );
            document.removeEventListener( 'keyup', onDocumentKeyUp );
            document.removeEventListener( 'mousedown', onDocumentMouseDown );
            document.removeEventListener( 'mouseup', onDocumentMouseUp );
            document.removeEventListener( 'mousemove', onDocumentMouseMove );
            document.removeEventListener( 'touchstart', onDocumentTouchStart );
            document.removeEventListener( 'touchend', onDocumentTouchEnd );
            document.removeEventListener( 'touchmove', onDocumentTouchMove );
            dispatch( events.stop, arguments );
            renderer.setAnimationLoop( null );
        };
        this.dispose = function () {
            while ( dom.children.length ) {
                dom.removeChild( dom.firstChild );
            }
            renderer.dispose();
            camera = undefined;
            scene = undefined;
            renderer = undefined;
        };
        //
        function onDocumentKeyDown( event ) {
            dispatch( events.keydown, event );
        }
        function onDocumentKeyUp( event ) {
            dispatch( events.keyup, event );
        }
        function onDocumentMouseDown( event ) {
            dispatch( events.mousedown, event );
        }
        function onDocumentMouseUp( event ) {
            dispatch( events.mouseup, event );
        }
        function onDocumentMouseMove( event ) {
            dispatch( events.mousemove, event );
        }
        function onDocumentTouchStart( event ) {
            dispatch( events.touchstart, event );
        }
        function onDocumentTouchEnd( event ) {
            dispatch( events.touchend, event );
        }
        function onDocumentTouchMove( event ) {
            dispatch( events.touchmove, event );
        }
    }
};
export { APP };

旁注:我注意到 Three.js 编辑器已经生成了许多事件侦听器。他们目前似乎没有做任何事情,但也许他们可以从脚本外部调用,例如在我的 index.html 中???

无论如何,为了用鼠标滚轮控制 PerspectiveCamera 的 Y 轴位置,我需要在 app.js 文件中的何处以及如何放置 OrbitControls?

【问题讨论】:

标签: three.js


【解决方案1】:

或者(甚至更理想),有没有办法在 Three.js 编辑器本身中定义我想要的相机行为?

很遗憾,没有。您只能使用EditorControls定义的默认控件,该类类似于OrbitControls,但仅在编辑器中使用。

我如何利用 OrbitControls 来实现这一点?

如果不更改app.js,恐怕这是不可能的。相机和渲染器在APP.Player 中创建,不可公开访问。由于创建OrbitControls 需要这两个对象,因此无法实例化index.html 中的控件。

如果您决定更改 app.js,如果您通过 ES6 导入包含 OrbitControls,请使用以下代码创建控件:

var controls = new OrbitControls( camera, renderer.domElement );

three.js R112

【讨论】:

  • 谢谢!这是一个很好的开始!好的,所以我必须在 APP.Player 中导入 OrbitControls?
  • 谢谢!我试过了,但我不知道如何/在哪里实现它。我编辑了我的问题以显示我的 app.js 文件,以及我的问题的更多细节。如果你有时间看,我真的很感激!
  • 嗯,我没有在您的代码中看到您创建 OrbitControls 的位置。打完setCamera()之后可以试试吗?
  • 是的,到目前为止我所做的只是导入脚本。是的,我可以在那里编码。我只是不知道要添加什么。也许:var controls = new THREE.OrbitControls( camera, renderer.dom );controls.addEventListener( 'change', render );
  • 不。那没有用。错误提示 THREE.OrbitControls is not a constructor
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-11
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多