✅代わりに「navigator.vibrate?.()」と書くと安全です
iOS端末(※ブラウザは問わない、SafariもChromeも)、及びMacパソコンのSafariでは、navigator.vibrate()を呼んだ時点でそこでコードが止まります!⚠️⚠️ そこ以降のコードも実行されなくなるため、
結果として、iPhoneやiPadの人からWebアプリが動かない‼と悲鳴が上がります。
* * *
navigator.vibrate()は、Webサイト上でJavascript側から端末を指定のミリ秒数だけ「バイブレーション」させることができます。
しかしこれ、このまま書いては上述の通り思わぬ事になるんです。
必ず、navigator.vibrate?.()と書くようにしてください。
気付かないうちに、自分のサイトの動作がiOS勢でだけ止まっているかもしれません。
navigator.vibrate(); 👈iOS,Safari(+Firefoxも)で停止します
navigator.vibrate?.(); 👈こちらの書き方が安全です
⭕安全な例
myButton.addEventListener("click",(e)=>{
navigator.vibrate?.(20); //👈「?.」をつける
・
・
・ //以降の処理
});
❌停止してしまう例(罠)
myButton.addEventListener("click",(e)=>{
navigator.vibrate(20); //👈iOSの全ブラウザ、macのSafari、Firefoxで止まる
・ //⚠️Exception: vibrate is not a function
・
・ //上の行で止まってしまうので、以降の処理も行われない
});
なぜiOSやSafariで停止してしまう?
navigator.vibrate()関数(Vibration API)は、Apple製ブラウザでは、そもそも存在しないのです。
↗Navigator: vibrate() メソッド (MDN Web Docs) > ブラウザーの互換性
このため、「❌navigator.vibrate is not a function」エラーで実行が止まります。
iOS上のブラウザは全てAppleが指定するレンダリングエンジンを使わないといけない事が定められているため、
単にSafariだけでなく、iOS版Chromeなどでも同じ挙動となります。
結果、「他のOSでは正常に動くサイトがiPhone勢でだけ停止する😱」ということになるので、気を付けた方がよさそうです。
標準化されている(HTML Living Standardに載っており標準外でない)機能でも、このようにBaseline(=実態として主要ブラウザで動く)でなく、動かない事があります。
※バイブ機能に対応しない場合は呼び出されても単純に何もしない、というのが
navigator.vibrate()の標準の仕様ですが、
iOSやSafariでは、セキュリティ重視のスタンスがあり、 標準外の挙動や仕様がたびたび存在します。 (この他にも、トラッキング防止を名目にlocalStorageのデータが即時~最長7日で消えるなど)
Webサイトがバイブ機能を使うべきではないというのがAppleのスタンスのようです。
Javascriptの「オプショナルチェーン」について
使用した「?.」は、オプショナルチェーン演算子といい、親オブジェクトがnullかundefinedであるかもしれない時に子プロパティを参照したい時などに便利です。
詳しくはこちら: ↗オプショナルチェーン演算子?. (MDN Web Docs)
let a = myObj.myProperty; 👈myObjがnullやundefinedだと、「❌Cannot read properties of null(undefined)」エラーを招く
let a = myObj?.myProperty; 👈myObjが空っぽであってもエラーを発生させない
関数を呼び出すときにも、()の前に?.を入れる事で使うことが可能です。
他にも、配列の[]の前にも入れることができます。
doSomething(); 👈doSomethingが無いか、あっても関数じゃない場合、「❌doSomething is not a function」エラーを招く
doSomething?.(); 👈doSomethingが関数でなくても問題ない
これはたとえば、ユーザーの端末上で使えなかったり、実装が古かったりするために使えなかったりする可能性がある API を使うときに役立ちます。↗MDN Web Docs