Skip to content
On this page

useGamepad

Category
Last Changed
2 months ago

Provides reactive bindings for the Gamepad API.

Demo

Gamepad is not supported on this device.It seems your device does not support the Gamepad API. Check here for a list supported devices.

Usage

Due to how the Gamepad API works, you must interact with the page using the gamepad before it will be detected.

<script setup>
import { useGamepad } from '@vueuse/core'

const { isSupported, gamepads } = useGamepad()
const gamepad = computed(() => gamepads.find(g => g.mapping === 'standard'))
</script>

<template>
  <span>
    {{ gamepad.id }}
  <span>
</template>
<script setup>
import { useGamepad } from '@vueuse/core'

const { isSupported, gamepads } = useGamepad()
const gamepad = computed(() => gamepads.find(g => g.mapping === 'standard'))
</script>

<template>
  <span>
    {{ gamepad.id }}
  <span>
</template>

Gamepad Updates

Currently the Gamepad API does not have event support to update the state of the gamepad. To update the gamepad state, requestAnimationFrame is used to poll for gamepad changes. You can control this polling by using the pause and resume functions provided by useGamepad

const { pause, resume, gamepads } = useGamepad()

pause()

// gamepads object will not update

resume()

// gamepads object will update on user input
const { pause, resume, gamepads } = useGamepad()

pause()

// gamepads object will not update

resume()

// gamepads object will update on user input

Gamepad Connect & Disconnect Events

The onConnected and onDisconnected events will trigger when a gamepad is connected or disconnected.

const { gamepads, onConnected, onDisconnected } = useGamepad()

onConnected((index) => {
  console.log(`${gamepads.value[index].id} connected`)
})

onDisconnected((index) => {
  console.log(`${index} disconnected`)
})
const { gamepads, onConnected, onDisconnected } = useGamepad()

onConnected((index) => {
  console.log(`${gamepads.value[index].id} connected`)
})

onDisconnected((index) => {
  console.log(`${index} disconnected`)
})

Vibration

The Gamepad Haptics API is sparse, so check the compatibility table before using.

const supportsVibration = computed(() => gamepad.hapticActuators.length > 0)
const vibrate = () => {
  if (supportsVibration.value) {
    const actuator = gamepad.hapticActuators[0]
    actuator.playEffect('dual-rumble', {
      startDelay: 0,
      duration: 1000,
      weakMagnitude: 1,
      strongMagnitude: 1,
    })
  }
}
const supportsVibration = computed(() => gamepad.hapticActuators.length > 0)
const vibrate = () => {
  if (supportsVibration.value) {
    const actuator = gamepad.hapticActuators[0]
    actuator.playEffect('dual-rumble', {
      startDelay: 0,
      duration: 1000,
      weakMagnitude: 1,
      strongMagnitude: 1,
    })
  }
}

Mappings

To make the Gamepad API easier to use, we provide mappings to map a controller to a controllers button layout.

Xbox360 Controller

<script setup>
import { mapGamepadToXbox360Controller } from '@vueuse/core'

const controller = mapGamepadToXbox360Controller(gamepad)
</script>

<template>
  <span>{{ controller.buttons.a.pressed }}<span>
  <span>{{ controller.buttons.b.pressed }}<span>
  <span>{{ controller.buttons.x.pressed }}<span>
  <span>{{ controller.buttons.y.pressed }}<span>
</template>
<script setup>
import { mapGamepadToXbox360Controller } from '@vueuse/core'

const controller = mapGamepadToXbox360Controller(gamepad)
</script>

<template>
  <span>{{ controller.buttons.a.pressed }}<span>
  <span>{{ controller.buttons.b.pressed }}<span>
  <span>{{ controller.buttons.x.pressed }}<span>
  <span>{{ controller.buttons.y.pressed }}<span>
</template>

Currently there are only mappings for the Xbox 360 controller. If you have controller you want to add mappings for, feel free to open a PR for more controller mappings!

Type Declarations

Show Type Declarations
export interface UseGamepadOptions
  extends ConfigurableWindow,
    ConfigurableNavigator {}
/**
 * Maps a standard standard gamepad to an Xbox 360 Controller.
 */
export declare function mapGamepadToXbox360Controller(
  gamepad: Ref<Gamepad | undefined>
): ComputedRef<{
  buttons: {
    a: GamepadButton
    b: GamepadButton
    x: GamepadButton
    y: GamepadButton
  }
  bumper: {
    left: GamepadButton
    right: GamepadButton
  }
  triggers: {
    left: GamepadButton
    right: GamepadButton
  }
  stick: {
    left: {
      horizontal: number
      vertical: number
      button: GamepadButton
    }
    right: {
      horizontal: number
      vertical: number
      button: GamepadButton
    }
  }
  dpad: {
    up: GamepadButton
    down: GamepadButton
    left: GamepadButton
    right: GamepadButton
  }
  back: GamepadButton
  start: GamepadButton
} | null>
export declare function useGamepad(options?: UseGamepadOptions): {
  isSupported: boolean | undefined
  onConnected: EventHookOn<number>
  onDisconnected: EventHookOn<number>
  gamepads: Ref<
    {
      readonly axes: readonly number[]
      readonly buttons: readonly {
        readonly pressed: boolean
        readonly touched: boolean
        readonly value: number
      }[]
      readonly connected: boolean
      readonly hapticActuators: readonly {
        readonly type: "vibration"
      }[]
      readonly id: string
      readonly index: number
      readonly mapping: GamepadMappingType
      readonly timestamp: number
    }[]
  >
  pause: Fn
  resume: Fn
  isActive: Ref<boolean>
}
export interface UseGamepadOptions
  extends ConfigurableWindow,
    ConfigurableNavigator {}
/**
 * Maps a standard standard gamepad to an Xbox 360 Controller.
 */
export declare function mapGamepadToXbox360Controller(
  gamepad: Ref<Gamepad | undefined>
): ComputedRef<{
  buttons: {
    a: GamepadButton
    b: GamepadButton
    x: GamepadButton
    y: GamepadButton
  }
  bumper: {
    left: GamepadButton
    right: GamepadButton
  }
  triggers: {
    left: GamepadButton
    right: GamepadButton
  }
  stick: {
    left: {
      horizontal: number
      vertical: number
      button: GamepadButton
    }
    right: {
      horizontal: number
      vertical: number
      button: GamepadButton
    }
  }
  dpad: {
    up: GamepadButton
    down: GamepadButton
    left: GamepadButton
    right: GamepadButton
  }
  back: GamepadButton
  start: GamepadButton
} | null>
export declare function useGamepad(options?: UseGamepadOptions): {
  isSupported: boolean | undefined
  onConnected: EventHookOn<number>
  onDisconnected: EventHookOn<number>
  gamepads: Ref<
    {
      readonly axes: readonly number[]
      readonly buttons: readonly {
        readonly pressed: boolean
        readonly touched: boolean
        readonly value: number
      }[]
      readonly connected: boolean
      readonly hapticActuators: readonly {
        readonly type: "vibration"
      }[]
      readonly id: string
      readonly index: number
      readonly mapping: GamepadMappingType
      readonly timestamp: number
    }[]
  >
  pause: Fn
  resume: Fn
  isActive: Ref<boolean>
}

Source

SourceDemoDocs

Contributors

wheat
三咲智子
Anthony Fu

Changelog

v8.4.0 on 5/3/2022
df9dd - fix(core): circular reference (#1553)
v8.0.0-beta.1 on 3/5/2022
50711 - feat: new function (#1355)
useGamepad has loaded