Making a simple Gamepad Web Component

Web Components 101

Diego González
Mar 5, 2018 · 6 min read

Para la versión en español, presiona aquí.

different states of the <game-pad> web component

I recently started working on an WebXR demo that would adapt to different platforms and available hardware configurations. The challenge here lies in making the most out of what you have available, and not dismissing some common devices that might aid or enhance the immersive experience. One of my favorite devices to add to the mix of Web applications is the gamepad. I find it so appealing because it’s far more common that many other hardware devices (you might even have access to one), it has a great support among browsers, comes in many shapes and sizes, and it has a known interaction model for many people (press a button and it’ll do something).

Gamepads. They’re more common than we think!

These characteristics make gamepads great devices to incorporate in the immersive demo I am coding (and in your projects). Now, while using the gamepad is relatively easy, it would be nice to abstract all the setting up and even provide a nice UI/badge that would show the state of the gamepad connection itself.

In a world of buzzwords and frameworks, it’s sometimes hard to identify a good option that will stand the test of time and tech. And while thinking on how to do this, I remembered a talk by Gil Fink on Web Components last year, and decided to give it a try to wrap some of the functionality of the Gamepad API, along with a nice GUI indicator. All this wrapped into a nice package which you can just drop into an HTML page and works seamlessly.

Welcome to Making a simple Gamepad Web Component 101.

Having said that, this is my first encounter with the technology, eager to see why maybe I should bet on Web Components as well. Welcome to Making a simple Gamepad Web Component 101.

The <game-pad> web component

Thinking about our simple example, we are creating a web component that initializes the Gamepad API in a webpage and sets a badge that can show the state of a Gamepad. This badge will be a white silhouette of a gamepad with a background in green (connected), yellow (awaiting connection) or red (not supported).

<game-pad> element in a web page in awaiting connection state

Custom Elements allow you to create a ‘element’ that encapsulates functionality. You can read all about them here, but for our interest all we need to know is that custom elements is the technology that allows us to create our own elements with custom ‘tags’ (the <game-pad> tag that is) that do something. As a useful piece of info, all newly invented tags must have at least a dash “-”.

Shadow DOM, is the one that permits us to create the DOM structure associated to the element, and this as a separate tree from the one of the main document. In our basic example, it consists of a div and an image (SVG icon of gamepad). This separate DOM tree also includes the styles that will change the background color of our component. You can read about Shadow DOM here.

Templates are not used in this first example, but using HTML templates and slots is a very powerful way to create more complex components. Since I am only using a div and an image, I wont be making use of them in this intro. But in a following post I will upgrade this component to show as many connected gamepads as connected to the browser. For this one, making a template will make sense because we will have repeating GUI (one badge per gamepad detected) in the page. You can read about HTML templates and slots here.

We wont enter to discuss HTML Imports at the moment, due to the fact that there is not consensus on the standard itself, so for the moment I will try to keep all the component self contained in the JavaScript file. For support in browsers that do not support some of the technologies stated above, I am using the WebComponent Polyfill found here.

How to create the <game-pad> component

class GamepadWrapper extends HTMLElement

In this class we will attach a ShadowRoot element and build the structure of our element. This is done in the constructor of the element we are defining.

constructor(){
super();
let shadow = this.attachShadow({mode:'open'});
(...)
}

Once this is attached, we can start creating the desired structure, which again, in our case is a div, an image and styles to apply to them. See code here. Notice that the structure is created in the same way you would dynamically create elements with JavaScript. These are all appended to the (shadow)root. I have also included in the component code that checks if the API is supported, and registered the gamepad connection and disconnection events. These will be used to change the color of the background of the component using CSS classes.

Then we need to register the custom element we will want to use. I have chosen ‘game-pad’. Notice the dash in the middle, as required by the spec. You’ll also need the associated class that we created before as well.

customElements.define('game-pad', GamepadWrapper);

The first argument is the name we are giving to our component and the second argument is its associated class.

Using the <game-pad> web component

<game-pad> component running in Samsung Internet with connected controller

We can test locally that a page with a source like the one below will run and display a big gamepad badge.

<body>
<game-pad></game-pad>
</body>

Remembering that the specification is still very green and not supported by some major browsers, we will use the webcomponentsjs polyfill. In order to use this component we simply include the JavaScript file in the head of our file. Do take into consideration that there are different files depending on the features you want to polyfill. At the moment, you can go with the ‘ webcomponents-sd-ce.js’ since it includes shady DOM that allows scoped styling (but it is a bit bigger than the others).

<script src="js/gamepad-comp.js"></script>

The component itself takes care of initializing the Gamepad API, and sets an object named gamepads that has a reference to the connected controllers. You can set up in your script a RequestAnimationFrame that polls on the objects of gamepads and check for status of buttons and axes to control your web app.

In summary…

If you’re keen on more info, check out some lessons learnt by Ruth and Ada when they built their DJ web app. I will also follow up with an example that builds on this one by adding sizing and custom icons by the user.

Samsung Internet Developers

Writings from the Samsung Internet Developer Relations…

Thanks to Peter O'Shaughnessy, Ada Rose Cannon, and Daniel Appelquist

Diego González

Written by

stereoparallaxer & Product Manager @ Samsung

Samsung Internet Developers

Writings from the Samsung Internet Developer Relations Team. For more info see our disclaimer: https://hub.samsunginter.net/about-blog

Diego González

Written by

stereoparallaxer & Product Manager @ Samsung

Samsung Internet Developers

Writings from the Samsung Internet Developer Relations Team. For more info see our disclaimer: https://hub.samsunginter.net/about-blog

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store