Skip to content

useGamepad

Category
Export Size
1.47 kB
Last Changed
3 weeks ago

Provides reactive bindings for the Gamepad API.

Demo

Loading demo...

Usage

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

vue
<script setup lang="ts">
import { 
useGamepad
} from '@vueuse/core'
import {
computed
} from 'vue'
const {
isSupported
,
gamepads
} =
useGamepad
()
const
gamepad
=
computed
(() =>
gamepads
.
value
.
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

ts
import { 
useGamepad
} from '@vueuse/core'
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.

ts
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.

ts
import { 
computed
} from 'vue'
const
supportsVibration
=
computed
(() =>
gamepad
.hapticActuators.length > 0)
function
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

vue
<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!

SSR Compatibility

This component is designed to be used in the client side. In some cases, SSR might cause some hydration mismatches.

If you are using Nuxt, you can simply rename your component file with the .client.vue suffix (e.g., GamepadComponent.client.vue) which will automatically make it render only on the client side, avoiding hydration mismatches.

In other frameworks or plain Vue, you can wrap your usage component with a <ClientOnly> component to ensure it is only rendered on the client side.

Type Declarations

Show Type Declarations
ts
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
:
ComputedRef
<boolean>
onConnected
:
EventHookOn
<number>
onDisconnected
:
EventHookOn
<number>
gamepads
:
Ref
<
{ readonly
axes
:
ReadonlyArray
<number>
readonly
buttons
: readonly {
readonly
pressed
: boolean
readonly
touched
: boolean
readonly
value
: number
}[] readonly
connected
: boolean
readonly
id
: string
readonly
index
: number
readonly
mapping
:
GamepadMappingType
readonly
timestamp
:
DOMHighResTimeStamp
readonly
vibrationActuator
: {
playEffect
: (
type
:
GamepadHapticEffectType
,
params
?: GamepadEffectParameters,
) =>
Promise
<
GamepadHapticsResult
>
reset
: () =>
Promise
<
GamepadHapticsResult
>
} }[], | Gamepad[] | { readonly
axes
:
ReadonlyArray
<number>
readonly
buttons
: readonly {
readonly
pressed
: boolean
readonly
touched
: boolean
readonly
value
: number
}[] readonly
connected
: boolean
readonly
id
: string
readonly
index
: number
readonly
mapping
:
GamepadMappingType
readonly
timestamp
:
DOMHighResTimeStamp
readonly
vibrationActuator
: {
playEffect
: (
type
:
GamepadHapticEffectType
,
params
?: GamepadEffectParameters,
) =>
Promise
<
GamepadHapticsResult
>
reset
: () =>
Promise
<
GamepadHapticsResult
>
} }[] >
pause
:
Fn
resume
:
Fn
isActive
:
Readonly
<
ShallowRef
<boolean>>
} export type
UseGamepadReturn
=
ReturnType
<typeof
useGamepad
>

Source

SourceDemoDocs

Contributors

Anthony Fu
wheat
SerKo
Anthony Fu
Jelf
isolcat
Fernando Fernández
Robin
Aaron-zon
yue
Curt Grimes
Stefan
Antonin Rousset
丶远方
三咲智子

Changelog

v13.6.0 on
d32f8 - refactor: add @__NO_SIDE_EFFECTS__ annotations to all pure functions (#4907)
v12.4.0 on
dd316 - feat: use passive event handlers everywhere is possible (#4477)
v12.0.0-beta.1 on
0a9ed - feat!: drop Vue 2 support, optimize bundles and clean up (#4349)
v10.10.0 on
2ccbd - fix: avoid spread to fix gamepad state (#3913)
v10.8.0 on
9b8ed - fix: improve data updating logic (#3775)
8c735 - fix: explicitly ensure gamepad index is available (#3653)

Released under the MIT License.