Orbit cam controls using keyboard

Hi,

I want to implement custom keyboard shortcuts for zoom and pan. Turned on the enable keys property of the orbit cam, but it doesn’t work. Any examples or suggestions on how to implement this?

Hi Ashok,

By default the OrbitControls component’s enableKeys property should allow keyboard interactions, but in practice it’s sometimes easier and more flexible to implement your own shortcuts. One common issue is that the canvas may not be focused or the default key mappings aren’t what you need. A typical solution is to attach a custom Behavior that listens to keyboard input through Needle Engine’s input system and then calls the appropriate OrbitControls functions for zooming (using dollyIn/dollyOut) and panning by adjusting the target.

Below is an example component in TypeScript that demonstrates this approach:


import { Behaviour, OrbitControls } from "@needle-tools/engine";
import { Vector3 } from "three";

export class OrbitKeyboardController extends Behaviour {
  private orbit?: OrbitControls;

  awake() {
    // Retrieve the OrbitControls component from the same GameObject.
    this.orbit = this.gameObject.getComponent(OrbitControls);
    if (!this.orbit) {
      console.error("OrbitControls component not found. Please add it to the GameObject.");
    }
  }

  update() {
    if (!this.orbit) return;

    const input = this.context.input;
    const zoomFactor = 0.95; // Lower than 1 zooms in, greater than 1 zooms out.
    const panStep = 0.1;

    // Zoom in with "Z" and zoom out with "X"
    if (input.getKey("KeyZ")) {
      this.orbit.controls?.dollyIn(zoomFactor);
      this.orbit.controls?.update();
    }
    if (input.getKey("KeyX")) {
      this.orbit.controls?.dollyOut(zoomFactor);
      this.orbit.controls?.update();
    }

    // Pan using arrow keys by adjusting the OrbitControls target
    if (input.getKey("ArrowLeft")) {
      this.orbit.target.x -= panStep;
      this.orbit.controls?.update();
    }
    if (input.getKey("ArrowRight")) {
      this.orbit.target.x += panStep;
      this.orbit.controls?.update();
    }
    if (input.getKey("ArrowUp")) {
      this.orbit.target.y += panStep;
      this.orbit.controls?.update();
    }
    if (input.getKey("ArrowDown")) {
      this.orbit.target.y -= panStep;
      this.orbit.controls?.update();
    }
  }
}

In this example the component:

• Retrieves the OrbitControls component from the GameObject in awake().
• Uses Needle Engine’s context.input (which now supports getKey as noted in recent updates at CHANGELOG.md) to listen for specific key presses.
• Calls dollyIn/dollyOut on the underlying OrbitControls from three.js for zooming and directly adjusts the target vector for panning.

If you still want to use the built-in keyboard support, double‑check that the canvas element is focused (for example, by setting tabindex=“0” on your canvas) and that the default key mappings (set in OrbitControls’ keys property) match your desired behavior. However, the custom component approach gives you full control over which keys trigger which behavior.

Let me know if you run into any issues or need further customizations. Happy coding!

4 replies left
thread_Ibih1eDLwKSsGuDGINmggaFr
Reply to this post directly if you need further help (bottom right button)

Hi, can you try setting tabindex to “0” on the needle-engine element?

E.g. <needle-engine tabindex=”0”> in your HTML code?

Yes, it works now, thanks! But can I remap those keys? I also need to implement shortcuts for both zoom and rotate. Do you have any suggestions for this?

Query or reference the OrbitControls component. It wraps around the three.js ObritControls

onStart(ctx => {
  const orbit = findObjectOfType(OrbitControls); // the needle engine orbitcontrols component https://engine.needle.tools/docs/api/classes/Built-in_Components.OrbitControls.html
  const threeOrbit = orbit.controls; // https://threejs.org/docs/#examples/en/controls/OrbitControls
});

So you can update the keys with threeOrbit.keys = { … }

By shortcuts for zoom and rotate you mean using keyboard keys to zoom in or to orbit? I dont think those values are currently exposed in three.js’ OrbitControls implementation

I need to assign key combinations like Control + Arrow Up. Also, yes I want to assign keyboard shortcuts for orbiting around and zooming in and out as well. Is that possible?

Hey, you can access the underlying methods of three.js OrbitControls directly:

document.body.addEventListener("keydown", (e) => {
    const controls = GameObject.findObjectOfType(OrbitControls)?._controls as any;
    // We can access the internal methods of three.js OrbitControls here
    if (e.code === "ArrowLeft") {
        controls._rotateLeft(0.1);
    }
    else if (e.code === "ArrowRight") {
        controls._rotateLeft(-0.1);
    }
    else if (e.code === "ArrowUp") {
        controls._rotateUp(0.1);
    }
    else if (e.code === "ArrowDown") {
        controls._rotateUp(-0.1);
    }
    else if (e.code === "KeyT") {
        controls._dollyIn(1.1);
    }
    else if (e.code === "KeyZ") {
        controls._dollyOut(1.1);
    }
});

We’ll take a look if we can make this more discoverable (by exposing methods on Needle OrbitControls), but the above should unblock you right away.

Hi, thanks.
I also want to remap the default keys for pan as well — I need to make them work with Control + a key combination. Do you have any suggestions for that?

For pan there’s also a _pan(deltaX, deltaY) method (same code as above). DeltaX etc is in pixels for pan.

The next update will make it easier to use those methods

Thanks a lot!

Hey, the update works pretty well — thanks a lot! For rotation, there seems to be only one method called rotateLeft. Is there anything like rotateUp or rotateDown?

Hi, sorry looks like rotateUp is missing - it’ll be added in the next release. Until then you can use needleObritControlsComponent._controls?._rotateUp(angleInRadians);

Thanks again!

This topic was automatically closed 13 days after the last reply. New replies are no longer allowed.