The navigator.vibrate() interface will crash iPhones, so only use it after checking if the user's device supports it
3 min read
At the spot in our code where we want to cause the phone to vibrate, just use
navigator.vibrate(200); The 200 represents the number of milliseconds the vibration should last, and can of course be changed. For multiple pulses in a pattern, pass in an array of values. The array defines alternating times that the phone vibrates, pauses, vibrates, and so on:
navigator.vibrate([400, 300, 400])
Here the phone would vibrate for 400ms, stop for 300ms, then vibrate again for 400ms. There can be as many vibration/pause pairs "as you would like," according to Mozilla Developer Network (MDN) docs. But don't get too crazy, less is more here. No one wants their phone constantly vibrating every time something happens in a game. For haptic feedback on a button press, a very short time such as 50ms is probably about right.
The unfortunate reality about the vibration API is that this will only work on Android phones because Apple does not support it. Here is a Stack Overflow comment on the subject:
> From the developer prospective (trying to build an awesome website), it seems ridiculous that the vibration apis are not exposed for use on iOS; after all, it has been available in other browsers for almost 8 years. But when looked upon from Apple's perspective... think of all the terrible websites that would ruin your browsing experience by spamming vibration. They are smart enough to see that it would turn into another pop-up-ocalypse. And that is why we can't have nice things. -isaacdre >
In fact, just calling navigator.vibrate() when the user is on an Apple iPhone causes the entire program to freeze. But it's not an insurmountable problem.
A crashing Apple device can be prevented by first checking whether the device supports the navigator.vibrate() interface. Above the location where we actually want the vibration to happen, we can write this:
let canVibrate = false; if('vibrate' in navigator) canVibrate = true;
We are creating a canVibrate variable that is set to false. It is then set to true only if the device supports the vibration interface. Then, at the spot where we want to cause the vibration, simply wrap it in an if block that checks if canVibrate is true:
if (canVibrate) navigator.vibrate(500);
What happens is that this will cause the vibration on Android phones, and do nothing on iPhones. The iPhone won't vibrate, but it also won't crash the website.
It's possible to stop any ongoing vibrations by calling
navigator.vibrate(0); However, it seems like a bad idea to be causing so much vibration or using setInterval() with this that we would need to stop the vibration.
What is navigator?
> The Navigator interface represents the state and the identity of the user agent. It allows scripts to query it and to register themselves to carry on some activities. A Navigator object can be retrieved using the read-only window.navigator property. >
The navigator interface also gives us a number of other things like navigator.geolocation that can be used to get a geolocation object and use the location of the device.
Use navigator.vibrate(500) (or another number of milliseconds) to cause a vibration on a mobile device. But it will crash an iPhone since Apple doesn't support the interface, so it's best write code that first checks if the interface is supported.