• Public
  • Public/Protected
  • All

Handles pointer events (mouse, touch, stylus, etc.) and normalizes to W3C Pointer Events.

There is always at least one Pointer available (Pointers.primary) and you can request multiple pointers to support multi-touch scenarios.

Since Pointers.primary normalizes both mouse and touch events, your game automatically supports touch for the primary pointer by default. When you handle the events, you can customize what your game does based on the type of pointer, if applicable.

Excalibur handles mouse/touch events and normalizes them to a PointerEvent that your game can subscribe to and handle (engine.input.pointers).


You can subscribe to pointer events through engine.input.pointers.on. A PointerEvent object is passed to your handler which offers information about the pointer input being received.

  • down - When a pointer is pressed down (any mouse button or finger press)
  • up - When a pointer is lifted
  • move - When a pointer moves (be wary of performance issues when subscribing to this)
  • cancel - When a pointer event is canceled for some reason
engine.input.pointers.primary.on('down', function(evt) {});
engine.input.pointers.primary.on('up', function(evt) {});
engine.input.pointers.primary.on('move', function(evt) {});
engine.input.pointers.primary.on('cancel', function(evt) {});

Wheel Event

You can also subscribe to the mouse wheel event through engine.input.pointers.on. A WheelEvent object is passed to your handler which offers information about the wheel event being received.

  • wheel - When a mousewheel is activated (trackpad scroll or mouse wheel)
engine.input.pointers.on('wheel', function(evt) {});

Last position querying

If you don't wish to subscribe to events, you can also access the Pointer.lastPagePos, Pointer.lastScreenPos or Pointer.lastWorldPos coordinates (Vector) on the pointer you're targeting.


Note that the value may be null if the Pointer was not active the last frame.

Pointer scope (window vs. canvas)

You have the option to handle all pointer events in the browser by setting EngineOptions.pointerScope to PointerScope.Document. If this is enabled,

Excalibur will handle every pointer event in the browser. This is useful for handling complex input and having control over every interaction.

You can also use PointerScope.Canvas to only scope event handling to the game canvas. This is useful if you don't care about events that occur outside the game.

One real-world example is dragging and gestures. Sometimes a player will drag their finger outside your game and then into it, expecting it to work. If PointerScope is set to Canvas this will not work. If it is set to Document, it will.

Responding to input

The primary pointer can be a mouse, stylus, or single finger touch event. You can inspect what type of pointer it is from the PointerEvent handled.

engine.input.pointers.primary.on('down', function(pe) {
  if (pe.pointerType === ex.Input.PointerType.Mouse) {
    ex.Logger.getInstance().info('Mouse event:', pe);
  } else if (pe.pointerType === ex.Input.PointerType.Touch) {
    ex.Logger.getInstance().info('Touch event:', pe);

Multiple Pointers (Multi-Touch)

When there is more than one pointer detected on the screen, this is considered multi-touch. For example, pressing one finger, then another, will create two pointers. If you lift a finger, the first one remains and the second one disappears.

You can handle multi-touch by subscribing to however many pointers you would like to support. If a pointer doesn't yet exist, it will be created. You do not need to check if a pointer exists. If it does exist, it will propagate events, otherwise it will remain idle.

Excalibur does not impose a limit to the amount of pointers you can subscribe to, so by all means, support all 10 fingers.

Note: There is no way to identify touches after they happen; you can only know that there are n touches on the screen at once.

function paint(color) {
  // create a handler for the event
  return function(pe) {
    if (pe.pointerType === ex.Input.PointerType.Touch) {
      engine.canvas.fillStyle = color;
      engine.canvas.fillRect(pe.x, pe.y, 5, 5);
engine.input.pointers.at(0).on('move', paint('blue')); // 1st finger
engine.input.pointers.at(1).on('move', paint('red')); // 2nd finger
engine.input.pointers.at(2).on('move', paint('green')); // 3rd finger

Actor pointer events

By default, Actors do not participate in pointer events. In other words, when you "click" an Actor, it will not throw an event for that Actor, only a generic pointer event for the game. This is to keep performance high and allow actors to "opt-in" to handling pointer events. Actors will automatically opt-in if a pointer related event handler is set on them actor.on("pointerdown", () => {}) for example.

To opt-in manually, set Actor.enableCapturePointer to true and the Actor will start publishing pointerup and pointerdown events. pointermove events will not be published by default due to performance implications. If you want an actor to receive move events, set CapturePointerConfig.captureMoveEvents to true.

Actor pointer events will be prefixed with pointer.

var player = new ex.Actor();
// enable propagating pointer events
player.enableCapturePointer = true;
// enable move events, warning: performance intensive!
player.capturePointer.captureMoveEvents = true;
// subscribe to input
player.on('pointerup', function(ev) {
  player.logger.info('Player selected!', ev);








eventDispatcher: EventDispatcher

Direct access to the game object event dispatcher.


primary: Pointer

Primary pointer (mouse, 1 finger, stylus, etc.)



  • Safely gets a Pointer at a specific index and initializes one if it doesn't yet exist


    • index: number

      The pointer index to retrieve

    Returns Pointer


  • checkAndUpdateActorUnderPointer(actor: Actor): void


  • count(): number


  • dispatchPointerEvents(): void


  • emit(eventName: string, eventObject: GameEvent<any>): void


  • init(target?: GlobalEventHandlers): void


  • off(eventName: string, handler?: function): void
  • Alias for removeEventListener. If only the eventName is specified it will remove all handlers registered for that specific event. If the eventName and the handler instance are specified only that handler will be removed.


    • eventName: string

      Name of the event to listen for

    • Optional handler: function

      Event handler for the thrown event

    Returns void


  • on(eventName: Events.up, handler: function): void
  • on(eventName: Events.down, handler: function): void
  • on(eventName: Events.move, handler: function): void
  • on(eventName: Events.enter, handler: function): void
  • on(eventName: Events.leave, handler: function): void
  • on(eventName: Events.cancel, handler: function): void
  • on(eventName: Events.wheel, handler: function): void
  • on(eventName: string, handler: function): void


  • once(eventName: string, handler: function): void
  • Once listens to an event one time, then unsubscribes from that event


    • eventName: string

      The name of the event to subscribe to once

    • handler: function

      The handler of the event that will be auto unsubscribed

    Returns void


  • Synthesize a pointer event that looks like a real browser event to excalibur


    • eventName: "up" | "down" | "move" | "cancel" | "wheel"
    • pos: Vector | GlobalCoordinates
    • Default value button: NativePointerButton = NativePointerButton.Left
    • Default value pointerType: "mouse" | "touch" | "pen" = "mouse"
    • Default value pointerId: number = 0

    Returns void


  • update(): void