OrbiterControls not working properly in three.js app

Solution 1:

The code needed several modifications. Use the code below instead and compare it with yours to find out which parts did I change.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My first three.js app</title>
        <style>
            body {
                padding: 0;
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
        <script type="module">
            import * as THREE from 'https://threejs.org/build/three.module.js';
            import {OrbitControls} from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';

            // BUILDING THE SCENE
            const scene = new THREE.Scene();

            // ADDING CAMERA
            const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, -5, 5);
            scene.add(camera);

            // CREATING THE RENDERER
            const renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            // ADD LIGHT
            const light = new THREE.PointLight(0xffffff, 2);
            light.position.set(0, 5, 10);
            scene.add(light);

            // ADD ORBITER
            const controls = new OrbitControls(camera, renderer.domElement);
            controls.maxPolarAngle = Math.PI/2.2;
            controls.minDistance = 5;
            controls.maxDistance = 10;
            controls.target.set(0, 0, 0);

            // ADD CUBE
            const geometry = new THREE.BoxGeometry();
            const material = new THREE.MeshBasicMaterial({color: 0x00ff00});
            const cube = new THREE.Mesh(geometry, material);
            cube.position.set(0, .5, 0);
            scene.add(cube);

            // ADD MAP
            const loader = new THREE.TextureLoader();
            const height = loader.load('/data/images/height.png');
            const texture = loader.load('/data/images/height.png');

            const map_geometry = new THREE.PlaneBufferGeometry(10,10,64,64);
            const map_material = new THREE.MeshStandardMaterial({
                color:'orange',
                side: THREE.DoubleSide,
                map:texture,
                displacementMap: height,
                displacementScale: 0.5,
            });

            const map_plane = new THREE.Mesh(map_geometry, map_material);
            map_plane.rotation.x = Math.PI/2;
            scene.add(map_plane);

            window.addEventListener('resize', onWindowResize, false);

            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
            }

            // ANIMATING THE SCENE
            function animate() {
                controls.update();
                requestAnimationFrame(animate);
                renderer.render(scene, camera);
            }
            animate();
        </script>
    </body>
</html>
  1. Write controls.update(); in the animate function.
  2. controls.maxPolarAngle = Math.PI/2.2; doesn't let the camera to go under the ground.
  3. controls.target.set(0, 0, 0); makes the control stair at the center.
  4. I added map_plane.rotation.x = Math.PI/2; so the plane will be placed horizontally as the floor.
  5. And side: THREE.DoubleSide, helps the floor to be visible from all angels.
  6. I also added an onWindowResize function to the script to make the applicaion responsive. Now, it'll response to the browser's width and height when its resized.
  7. In case of CSS, the page has default padding as well. So, adding a padding: 0; to the CSS code is not a bad idea as well.