色が変わるしくみ

石際です。こんにちは。読んでいただいてありがとうございます。

今回のTeam.KFC Season2では、モバイル端末を振ると色が変わる仕組みを作りました。どのように色が変わっているか、ここで説明してみたいと思います。

DeviceMotionEvent

スマートフォンの加速度センサーから「どのくらいデバイスが動いているか」を取得するために、DeviceMotionEventを利用することができます。
以下は、実際に動作しているコードです。

window.ondevicemotion = (ev) => {
    if (Math.max(
        ev.acceleration?.x ?? 0,
        ev.acceleration?.y ?? 0,
        ev.acceleration?.z ?? 0
    ) < 4) return;

    dispatch(furufuruSlice.actions.add())
}

alert('加速度センサーの使用を許可しました。');

return dispatch(permissionSlice.actions.askTorch({ deviceMotion: true }))

DeviceMotionイベントが発生すると、Event.acceleration.x(y,z)からその加速度を取得できます。

ただし、この加速度センサーはかなり感度が高いので、閾値を設定しないと何度もイベントが連続して発生してしまいます。

みなさんがフルフルして応援していただいた、「ライブサイリウム」の閾値は4, 森田部長がフルフルして承認してくださった「フルフル承認機能」では閾値14になっています。

DeviceMotionイベントは事前にユーザーの許可が必要になる機能です。ライブサイリウムでは以下のようにボタンを押したときにユーザーに許可を促しています。

const requestPermission = (DeviceMotionEvent as any).requestPermission;
const state = null == requestPermission ? 'granted' : await requestPermission();

色相環(HSL色空間)

色空間はパラメータにより色を分化した座標で指定する仕組みです。
よくみたことがあるのはRGB色空間でこれはR(赤)、G(みどり)、B(青)のパラメータによって色が構成される座標空間です。

色相環はRGBとは違った座標空間で、色相 (Hue)、彩度 (Saturation)、輝度(Lightness)で構成されています。

色相は環状になるので、カラーホイールとも呼ばれています。これは色みを360度の角度で表していて、対角にある色が「補色」で、反対側にある色になります(いっしょにすると際立つ色)

今回は彩度と輝度を保ったまま、色相をモバイルデバイスの加速度に合わせて加算して、360度のカラーホイール上をぐるぐると回転させて色を変えています。

下記は実際に動作しているコードです。

if (mode == 'local') {
    background = `hsl(${value},50%,50%)`;
} else {
    background = `linear-gradient(180deg, hsl(${value},50%,50%) 0%, hsl(${synchroHue},50%,50%) 100%)`;
}

modeはライブ動作しているかどうかを表す変数です。

valueが加速度の合計、つまりモバイルデバイスのユーザーがどのくらい振ってくれているかを表現しています。

synchroHueはライブに参加している全員のフルフルポイントを色相にした値です。

ですから、ライブ中はたくさん振ると上の方の色が変わり、下の方の色はみんな同じ色になります。

まとめ

  • モバイルデバイスのフルフルにはDeviceMotionEventを利用している。
  • 加速度センサーは感度が高いので、調整が必要
  • 加速度センサーの利用にはユーザーの許可が必要
  • 色が変わる仕組みはHSL色空間の色相環(カラーホイール)を利用している。