Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
20
Help us understand the problem. What are the problem?
@mascii

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

以前に 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=>{const c=a.activeElement,d="IFRAME"===c.tagName?c.contentDocument:a;["keydown","keyup"].forEach(a=>{d.body.dispatchEvent(new KeyboardEvent(a,{keyCode:b,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(37),!0):b[3].pressed?(c||d(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回振動する
    • スクリーンショットのキャプチャーボタンを押すと、コントローラーが少し振動する

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
20
Help us understand the problem. What are the problem?