# Unable to move in a Three.js scene?

**URL:** <https://discourse.threejs.org/t/unable-to-move-in-a-three-js-scene/75792>\
**Category:** Questions\
**Created:** [December 29, 2024, 9:46pm UTC](https://discourse.threejs.org/t/unable-to-move-in-a-three-js-scene/75792 "2024-12-29T21:46:30Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dams-webdesign](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/dams-webdesign/32/55059_2.png) [@dams-webdesign](https://discourse.threejs.org/u/dams-webdesign)\
**Post date:** [December 29, 2024, 9:46pm UTC](https://discourse.threejs.org/t/unable-to-move-in-a-three-js-scene/75792/1 "2024-12-29T21:46:30Z")

</div>

Hello everyone!

I currently have this script here: [Nabil - Photos THREE JS](https://test-36651c-d705439d8aafd-6db1427885413.webflow.io/nabil---photos-three-js-copy)

… but I would like to have the same movement capability (via the MacBook trackpad) as this website: [SOOT](https://play.soot.com/sootworld)

Here is my current script:

```javascript
<script>

// Variables globales
let camera, scene, renderer;
let images = [];
let frustum;
let cameraViewProjectionMatrix;
const IMAGE_LOAD_DISTANCE = 50;
let imageBoundingBox;
let minZoom = 0, maxZoom = 50; // Valeurs initiales, peuvent être ajustées dynamiquement
let targetZPosition = 30;

// Initialisation Three.js
function initThreeJS() {
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xf5f5f5);

    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = targetZPosition;

    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    const canvasContainer = document.getElementById('canvas-container');
    if (canvasContainer) { // Vérification pour éviter une erreur si l'élément n'existe pas
        canvasContainer.appendChild(renderer.domElement);
    } else {
        console.error("Élément 'canvas-container' non trouvé.");
    }

    frustum = new THREE.Frustum();
    cameraViewProjectionMatrix = new THREE.Matrix4();
}

// Gestionnaire de chargement d'images (amélioré)
function loadImage(url, index, callback) {
    const loader = new THREE.TextureLoader();
    loader.load(url, texture => callback(texture, index), undefined, error => console.error(`Erreur de chargement de ${url}:`, error));
}

// Charge les images et les ajoute à la scène
function loadImages(imageUrls, scaleFactor) {
    const loadingManager = new THREE.LoadingManager();
    loadingManager.onProgress = (url, itemsLoaded, itemsTotal) => {
        const percent = (itemsLoaded / itemsTotal * 100).toFixed(0);
        const loadingIndicator = document.getElementById('loading-indicator') || createLoadingIndicator();
        loadingIndicator.textContent = `Chargement : ${percent}%`;
        if (itemsLoaded === itemsTotal) {
            setTimeout(() => (loadingIndicator.style.display = 'none'), 1000);
        }
    };

    imageUrls.forEach((url, index) => {
        loadImage(url, index, (texture, index) => {
            const width = texture.image.width * scaleFactor;
            const height = texture.image.height * scaleFactor;
            const geometry = new THREE.PlaneGeometry(width / 100, height / 100);
            const material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide, transparent: true, opacity: 1 });
            const mesh = new THREE.Mesh(geometry, material);
            mesh.position.x = (Math.random() - 0.5) * 80;
            mesh.position.y = (Math.random() - 0.5) * 40;
            mesh.position.z = (Math.random() - 0.5) * 10;
            mesh.userData.url = url;
            mesh.userData.highResLoaded = false;
            images.push(mesh);
            scene.add(mesh);
            if (index === imageUrls.length - 1) {
                calculateImageBounds();
            }
        });
    });
}

// Crée l'indicateur de chargement
function createLoadingIndicator() {
    const loadingIndicator = document.createElement('div');
    loadingIndicator.id = 'loading-indicator';
    loadingIndicator.style.cssText = `
        position: fixed;
        top: 20px;
        right: 20px;
        background: rgba(0,0,0,0.7);
        color: white;
        padding: 10px;
        border-radius: 5px;
        z-index: 1000;
    `;
    document.body.appendChild(loadingIndicator);
    return loadingIndicator;
}

// Calcule les limites de la boîte englobante des images
function calculateImageBounds() {
    imageBoundingBox = new THREE.Box3();
    images.forEach(mesh => imageBoundingBox.expandByObject(mesh));
    const size = new THREE.Vector3();
    imageBoundingBox.getSize(size);
    const diagonal = size.length();
    maxZoom = Math.max(50, diagonal * 2);
    camera.position.z = maxZoom * 0.5;
}

// Gestionnaire d'événements
function addEventListeners() {
    const canvas = renderer.domElement;
    let isDragging = false;
    let mouseDownPosition = null;
    let offsetX, offsetY;

    // Gestion du déplacement de la caméra avec la souris
    canvas.addEventListener('mousedown', (e) => {
        isDragging = true;
        mouseDownPosition = { x: e.clientX, y: e.clientY };
        e.preventDefault();
    });

    canvas.addEventListener('mousemove', (e) => {
        if (!isDragging) return;
        const deltaX = e.clientX - mouseDownPosition.x;
        const deltaY = e.clientY - mouseDownPosition.y;
        camera.position.x -= deltaX * 0.02;
        camera.position.y += deltaY * 0.02;
        mouseDownPosition = { x: e.clientX, y: e.clientY };
        e.preventDefault();
    });

    canvas.addEventListener('mouseup', () => { isDragging = false; });

    canvas.addEventListener('wheel', onWheel, { passive: false });
    canvas.addEventListener('click', onClick);

    // Gestion des événements tactiles (à réactiver si besoin)
    // ...
}

// Gestionnaire de l'événement wheel
function onWheel(event) {
    event.preventDefault();
    const zoomSpeed = 0.1;
    targetZPosition += event.deltaY * zoomSpeed;
    targetZPosition = Math.min(Math.max(targetZPosition, minZoom), maxZoom);
    camera.position.z = targetZPosition;
}

// Gestionnaire de clics sur les images
function onClick(event) {
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1);
    raycaster.setFromCamera(mouse, camera);
    const intersects = raycaster.intersectObjects(images);
    if (intersects.length > 0) {
        openImageSlider(intersects[0].object.userData.url);
    }
}

// Fonction pour ouvrir la boîte à lumière
function openImageSlider(imageUrl) {
    // ... (votre code existant) ...
}

// Gestionnaire de redimensionnement de la fenêtre
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    calculateImageBounds();
}

// Boucle d'animation
function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}

// Fonction d'initialisation principale
function init() {
    initThreeJS();
    const cmsImages = document.querySelectorAll('[data-img="person"]');
    const imageUrls = Array.from(cmsImages).map(img => img.src);
    const scaleFactor = 0.23;
    loadImages(imageUrls, scaleFactor);
    addEventListeners();
    animate();
}

document.addEventListener('DOMContentLoaded', init);
</script>

```

Can someone help me? Please.

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [December 30, 2024, 1:58am UTC](https://discourse.threejs.org/t/unable-to-move-in-a-three-js-scene/75792/2 "2024-12-30T01:58:07Z")

</div>

[https://threejs.org/docs/#examples/en/controls/OrbitControls](https://threejs.org/docs/#examples/en/controls/OrbitControls)

[https://threejs.org/examples/#misc\_controls\_orbit](https://threejs.org/examples/#misc_controls_orbit)

---

<div class="post-metadata">

**Author:** ![dams-webdesign](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/dams-webdesign/32/55059_2.png) [@dams-webdesign](https://discourse.threejs.org/u/dams-webdesign)\
**Post date:** [December 30, 2024, 7:46pm UTC](https://discourse.threejs.org/t/unable-to-move-in-a-three-js-scene/75792/3 "2024-12-30T19:46:56Z")

</div>

thanks for your message, but it’s not really the same way of moving around OrbitControl… Any idea how to move the camera with two fingers without having to click/drag?

---

<div class="post-metadata">

**Author:** ![GitHubDragonFly](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/githubdragonfly/32/20752_2.png) [@GitHubDragonFly](https://discourse.threejs.org/u/GitHubDragonFly)\
**Post date:** [December 30, 2024, 10:21pm UTC](https://discourse.threejs.org/t/unable-to-move-in-a-three-js-scene/75792/4 "2024-12-30T22:21:45Z")

</div>

Try using `pointerup` and `pointerdown` instead of `mousedown` and `mouseup` events. Maybe also check if there are any other pointer related events.

As for a test on your Mac, maybe try one of my viewers like [GLTF Viewer](https://githubdragonfly.github.io/viewers/templates/GLTF%20Viewer.html) to see what you get with touch controls. You should be able to paste the following link into the viewer’s URL text box and hit the `Load` button to load the model and start navigation:

`https://github.com/KhronosGroup/glTF-Sample-Models/blob/d7a3cc8e51d7c573771ae77a57f16b0662a905c6/2.0/DamagedHelmet/glTF-Binary/DamagedHelmet.glb`

---

<div class="post-metadata">

**Author:** ![manthrax](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/manthrax/32/2596_2.png) [@manthrax](https://discourse.threejs.org/u/manthrax)\
**Post date:** [December 30, 2024, 11:18pm UTC](https://discourse.threejs.org/t/unable-to-move-in-a-three-js-scene/75792/5 "2024-12-30T23:18:30Z")

</div>

There are a few configuration options for orbitcontrols that might enable the behavior you need:

[https://threejs.org/docs/#examples/en/controls/OrbitControls](https://threejs.org/docs/#examples/en/controls/OrbitControls)

[https://threejs.org/docs/#examples/en/controls/OrbitControls.mouseButtons](https://threejs.org/docs/#examples/en/controls/OrbitControls.mouseButtons)

[https://threejs.org/docs/#examples/en/controls/OrbitControls.touches](https://threejs.org/docs/#examples/en/controls/OrbitControls.touches)

```javascript
controls.touches = {
	ONE: THREE.TOUCH.ROTATE,
	TWO: THREE.TOUCH.DOLLY_PAN
}

```
