LoginSignup
43
21

More than 1 year has passed since last update.

【JavaScript】スイッチのJoy-Conをプレゼンリモコンにするワンライナー

Last updated at Posted at 2018-10-20

以前に Joystick Mapper という、ゲームパッドのボタンをキーに対応させる有料ツールを使ってJoy-Conをプレゼンリモコンにする方法が紹介されていました1が、ブラウザ上であればJavaScriptのワンライナーでJoy-Conをプレゼンリモコンにすることができます!

presentation-joy-con.gif

動作環境

  • macOS Catalina
  • Chrome 84
  • Joy-Con (L)

準備

Joy-Con (L) を macOS の標準の機能で接続しておきます。


矢印の部分にあるボタンを長押しすると、ペアリングモードに入ります。

スクリーンショット 2018-10-20 17.47.02.png

Joy-Conをプレゼンリモコンにするワンライナー

以下のスクリプトをデベロッパーツール(Macであればcommand+option+I)の Console に貼り付け Enter で実行します

((a,b,c)=>{const d=(b,c)=>{const d=a.activeElement,e="IFRAME"===d.tagName?d.contentDocument:a;["keydown","keyup"].forEach(a=>{e.body.dispatchEvent(new KeyboardEvent(a,{key:b,keyCode:c,bubbles:!0}))})},e=({vibrationActuator:a},b,c)=>a?a.playEffect(a.type,{startDelay:b,duration:c,strongMagnitude:.8}):Promise.resolve();let f,g;if(c("gamepadconnected",({gamepad:a})=>{if(null!=f||!a.id.includes("57e")||!a.id.includes("2006"))return;f=a.index;let c=!1;g=setInterval(()=>{c=(a=>{const b=a.buttons;return b[0].pressed?(c||d("ArrowLeft",37),!0):b[3].pressed?(c||d("ArrowRight",39),!0):!!b[16].pressed&&(c||e(a,0,10),!0)})(b.getGamepads()[f])},1e3/60);const h=()=>e(a,300,5);h().then(h).then(h)}),c("gamepaddisconnected",a=>{f===a.gamepad.index&&(clearInterval(g),f=g=null)}),b.wakeLock){const c=d=>{"visible"!==a.visibilityState||b.wakeLock.request("screen").then(()=>{d&&(a.addEventListener("visibilitychange",c),a.addEventListener("fullscreenchange",c))}).catch(()=>{})};c(!0)}})(document,navigator,addEventListener);

(minify前のコードはこちらにあります: https://github.com/mascii/presentation-joy-con/blob/master/src/presentation-joy-con.js )

ページが再読み込みされた場合には、再度上記のスクリプトを実行する必要があります。

利用するボタン

画像で図示したボタンでスライドを進めたり、戻したりすることができます。

スクリーンショットのキャプチャーボタンを押すと、コントローラーが少し振動します(疎通テスト用、Chrome などの対応ブラウザのみ)。

対応サイト

以下の対応サイトで利用できることを確認しました

解説

Gamepad APIを利用してJoy-Con (L)で押されたボタンを検知し、dispatchEventで左矢印キー・右矢印キーのイベント(keyupkeydown)を発火しています。

Joy-Conのボタンイベントの取得はWeb Bluetooth APIで頑張らないとできないのかな思っていましたが、調べていくうちにGamepad APIが使えること2がわかりました。
一方、矢印キーを押すイベントについてはGoogle スライドのようにiframeの中で発生させないといけないものもあることがわかり、複数サイトで対応させる方が大変でした。

コード

minify前のコードはこちらです:
https://github.com/mascii/presentation-joy-con
git clone, npm ci, npm run minify でminifyしたワンライナーを出力可能です。改善点ありましたら、ぜひPull Requestしてください!

(2020/07/24追記)

  • Chrome 84 から Screen Wake Lock API が利用可能となったので、対応ブラウザではディスプレイがオフにならないようにリクエストするようにしました(Pull Request)
  • Speaker Deck でスライド以外の要素が active のときにスライドを動かそうとするとエラーが発生する問題を修正しました(Pull Request)

(2021/02/07追記)

  • Chrome などの一部ブラウザで対応している Gamepad API の vibrationActuator を用いて、以下の対応をしました(Pull Request):
    • コントローラー接続時(gamepadconnected イベント発生時)に、コントローラーが小刻みに3回振動する
    • スクリーンショットのキャプチャーボタンを押すと、コントローラーが少し振動する

参考

43
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
21