This guide is designed to help you integrate the Gamepad API into your website, using the API to detect and interact with gamepads in real time. By the end of this guide, you will be able to create a gamepad testing page similar to gamepadtester.io, allowing users to connect and test gamepad devices directly in their browsers.
What is the Gamepad API?
Browser Support
Accessing the Gamepad API
Detecting Connected Gamepads
Polling Gamepad Inputs
Handling Multiple Gamepads
Gamepad API Events
Gamepad Buttons and Axes
Displaying Gamepad Input Data
Gamepad API Example Code
Testing the Gamepad
Troubleshooting Common Issues
The Gamepad API is a JavaScript API that allows web applications to interact with gamepad devices. It enables real-time access to gamepad hardware, providing information about connected controllers, including button presses, joystick positions, and more. This API is especially useful for creating browser-based games or gamepad testing tools.
Most modern browsers support the Gamepad API, but you need to ensure that your users are using a compatible version. Here’s a list of browsers that support the Gamepad API:
Google Chrome (version 35 and later)
Mozilla Firefox (version 29 and later)
Microsoft Edge (version 12 and later)
Opera (version 22 and later)
Safari (limited support)
Ensure your users are using the latest browser versions for the best experience.
To start using the Gamepad API, you need to access the navigator.getGamepads() method. This method returns an array of connected gamepads, which you can then poll for input.
Example of accessing the gamepads :
const gamepads = navigator.getGamepads(); // Get the list of connected gamepads
The gamepads array contains objects representing each connected gamepad. Each gamepad object provides details such as its ID, buttons, axes, and connection status.
To detect when a gamepad is connected or disconnected, you can use two event listeners: gamepadconnected and gamepaddisconnected.
window.addEventListener('gamepadconnected', (event) => {
console.log('Gamepad connected:', event.gamepad);
});
window.addEventListener('gamepaddisconnected', (event) => {
console.log('Gamepad disconnected:', event.gamepad);
});
When a gamepad is connected, the gamepadconnected event is triggered, allowing you to immediately start using the gamepad without refreshing the page.
To read input from the gamepad, you’ll need to poll the gamepad state at regular intervals (e.g., inside a requestAnimationFrame loop). This ensures that your application gets continuous input updates from the device.
Example of polling gamepad data:
function pollGamepads() {
const gamepads = navigator.getGamepads();
for (let i = 0; i < gamepads.length; i++) {
const gamepad = gamepads[i];
if (gamepad) {
// Process gamepad input here
}
}
// Repeat this at the next frame
requestAnimationFrame(pollGamepads);
}
requestAnimationFrame(pollGamepads);
The Gamepad API allows you to handle multiple gamepads connected simultaneously. The navigator.getGamepads() method returns an array where each index corresponds to a different gamepad.
Example of handling multiple gamepads:
const gamepads = navigator.getGamepads();
for (let i = 0; i < gamepads.length; i++) {
if (gamepads[i]) {
console.log(`Gamepad ${i}: ${gamepads[i].id}`);
}
}
Fired when a gamepad is connected.
Fired when a gamepad is disconnected.
You can use these events to update the UI when gamepads are connected or disconnected.
window.addEventListener('gamepadconnected', (event) => {
console.log(`Gamepad connected at index ${event.gamepad.index}: ${event.gamepad.id}`);
});
window.addEventListener('gamepaddisconnected', (event) => {
console.log(`Gamepad disconnected from index ${event.gamepad.index}: ${event.gamepad.id}`);
});
Gamepad objects contain two main input properties:
An array representing the state of each button (pressed or not).
An array representing the state of each joystick axis.
Each button has a pressed property that is true when the button is pressed.
const gamepad = navigator.getGamepads()[0]; // First gamepad
if (gamepad.buttons[0].pressed) {
console.log('Button A is pressed');
}
Each axis is represented as a floating-point value between -1.0 and 1.0.
const gamepad = navigator.getGamepads()[0]; // First gamepad
const leftStickX = gamepad.axes[0]; // Left joystick horizontal axis
const leftStickY = gamepad.axes[1]; // Left joystick vertical axis
console.log(`Left Stick X: ${leftStickX}, Y: ${leftStickY}`);
To create a visual representation of gamepad input (like on a gamepad tester), you’ll need to display the button and axis states dynamically.
Here’s a basic example of how you could display the data on a webpage:
<div id="gamepad-display"></div>
<script>
function displayGamepadStatus() {
const gamepads = navigator.getGamepads();
const display = document.getElementById('gamepad-display');
display.innerHTML = '';
for (let i = 0; i < gamepads.length; i++) {
const gamepad = gamepads[i];
if (gamepad) {
display.innerHTML += `<h3>Gamepad ${i}: ${gamepad.id}</h3>`;
gamepad.buttons.forEach((button, index) => {
display.innerHTML += `Button ${index}: ${button.pressed ? 'Pressed' : 'Released'}<br>`;
});
gamepad.axes.forEach((axis, index) => {
display.innerHTML += `Axis ${index}: ${axis.toFixed(2)}<br>`;
});
}
}
requestAnimationFrame(displayGamepadStatus);
}
requestAnimationFrame(displayGamepadStatus);
</script>
Below is a full example that includes connecting, polling, and displaying gamepad data:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gamepad Tester</title>
</head>
<body>
<h1>Gamepad Tester</h1>
<div id="gamepad-display"></div>
<script>
function pollGamepads() {
const gamepads = navigator.getGamepads();
const display = document.getElementById('gamepad-display');
display.innerHTML = '';
for (let i = 0; i < gamepads.length; i++) {
const gamepad = gamepads[i];
if (gamepad) {
display.innerHTML += `<h3>Gamepad ${i}: ${gamepad.id}</h3>`;
gamepad.buttons.forEach((button, index) => {
display.innerHTML += `Button ${index}: ${button.pressed ? 'Pressed' : 'Released'}<br>`;
});
gamepad.axes.forEach((axis, index) => {
display.innerHTML += `Axis ${index}: ${axis.toFixed(2)}<br>`;
});
}
}
requestAnimationFrame(pollGamepads);
}
requestAnimationFrame(pollGamepads);
window.addEventListener('gamepadconnected', (event) => {
console.log('Gamepad connected:', event.gamepad);
});
window.addEventListener('gamepaddisconnected', (event) => {
console.log('Gamepad disconnected:', event.gamepad);
});
</script>
</body>
</html>
To test the gamepad integration on your website:
Connect a gamepad to your computer.
Open your gamepad testing page.
Check if the gamepad is recognized and see if the inputs (buttons and axes) are displayed in real-time.
Ensure your browser supports the Gamepad API and your gamepad is properly connected.
Try refreshing the page or reconnecting the gamepad. Use the gamepadconnected event to verify when a gamepad is connected.
Different gamepads may have different button layouts. You may need to handle these variations in your code.
By following this guide, you should be able to build a fully functional gamepad tester similar to GamepadTester.io using the Gamepad API. This can be used for both game development and diagnostic purposes.
The Gamepad API provides a powerful way to interact with game controllers in web applications. By leveraging this API, you can create engaging experiences for users, such as gamepad testers or browser-based games. With this guide, you should have a good foundation to start working with gamepads in your own projects.