JSとCSSでデバイスの傾きを検知してホログラムを再現する
さいしょに
こんにちは つきやま です。
今回はデバイスの傾きを検知してホログラムを再現したので記事にしました。
デバイスの傾きの検知の仕方や、使用したCSSの関数についてまとめています。
デモ&ソースコード
下記ページで公開しています。
ソースコード
Nuxt3とスタイリングにTailwind CSSを使用しました。
<script setup lang="ts">
const alpha = ref<number | null>(null);
const beta = ref<number | null>(null);
const gamma = ref<number | null>(null);
/**
* refにイベントで取得した傾きを格納する
* @param e DeviceOrientationEvent
*/
const handleOrientation = (e: DeviceOrientationEvent) => {
alpha.value = e.alpha;
beta.value = e.beta;
gamma.value = e.gamma;
};
/**
* gammaの度数を算出する
*/
const gammaDeg = computed(() => {
if (!gamma.value) return "0deg";
return `${(gamma.value + 90) * 2}deg`;
});
/**
* ユーザーの許可ボタン
*/
const requestDeviceOrientationPermission = () => {
if (
DeviceOrientationEvent &&
typeof DeviceOrientationEvent.requestPermission === "function"
) {
DeviceOrientationEvent.requestPermission()
.then((permissionState: string) => {
if (permissionState === "granted") {
window.addEventListener(
"deviceorientation",
(e: DeviceOrientationEvent) => {
handleOrientation(e);
}
);
}
})
.catch(console.error);
}
};
</script>
<template>
<div class="space-y-4">
<div class="flex h-[50vh] justify-center items-center">
<div
class="hologram w-[300px] h-[300px] flex items-center justify-center bg-[length:30px_30px]"
>
<img
src="画像URL"
width="300"
/>
</div>
</div>
<div class="text-center">
<p>alpha: {{ Math.round(alpha ?? 0) ?? "-" }}</p>
<p>beta: {{ Math.round(beta ?? 0) ?? "-" }}</p>
<p>gamma: {{ Math.round(gamma ?? 0) ?? "-" }}</p>
</div>
<div class="flex justify-center">
<button
@click="requestDeviceOrientationPermission"
class="text-base bg-emerald-400 rounded-md px-6 py-3 text-white cursor-pointer"
>
傾きを検知する
</button>
</div>
</div>
</template>
<style scoped>
.hologram {
background-image: repeating-conic-gradient(
from v-bind(gammaDeg),
rgb(0, 34, 255) 0%,
rgb(0, 255, 242) 25%,
rgb(255, 255, 255) 50%,
rgb(0, 255, 242) 75%,
rgb(0, 34, 255) 100%
);
filter: drop-shadow(4px 4px 4px rgb(0, 0, 0));
}
</style>
ソースコードもGitHubで公開しているので興味がある方はこちらからご確認ください。
実装
デバイス傾斜感知
JavaScriptではDeviceOrientationEvent
というデバイスの傾きを検知するイベントが用意されています。
DeviceOrientationEventイベント
DeviceOrientationEvent
は、デバイスが物理的にどのように傾いているか(回転しているか)を示すイベントをブラウザで扱うための Web API です。
こちらのイベントを使用するにはイベントの許可を必要とします。
こちらの記事を参考に実装しました。
このようなダイアログが表示され、「許可」を押すとデバイスの傾きを取得できるようになります。
こちらが公式ドキュメントになります。
DeviceOrientationEvent
イベントは 4 つの値を持ちます。
- absolute
- alpha
- beta
- gamma
一つずつ確認していきましょう
absolute
デバイスが提供するオリエンテーションデータが絶対的なものであるか、相対的なものであるかを示す真偽値です。
-
true
デバイスのオリエンテーションデータは地球の重力に対して絶対的なものであると言えます。つまり、地球の表面に対して水平または垂直など、絶対的な基準に基づいています。 -
false
データはデバイスに対して相対的なものであり、デバイスが初めてDeviceOrientationEvent
を送信したときのオリエンテーションを基準にしています。
alpha
デバイスが z 軸周り(デバイスが直立しているときに上に向いている線)に沿って回転している角度を表す(0 から 360 までの)数値。
beta
x 軸周り(デバイスの側面)の前後の傾きを表す角度(-180 から 180 までの数値)。
gamma
y 軸周り(デバイスの上下の側面)の左右の傾きを表す角度(-90 から 90 までの数値)。
図で表すとこんな感じです。
conic-gradient()
ホログラムの模様を再現するためにconic-gradient()
というCSS関数を使用しました。
conic-gradient()
は円錐形のグラデーションを作成するために使われます。
よく見るところで言うとカラーピッカーでも使用されています。
使い方
conic-gradient()
の引数にグラデーションの情報を渡します。
conic-gradient(from 開始角度 at 中心点, 色停止点, 色停止点, ...)
色停止点は任意のカラーフォーマットで指定でき、位置はパーセンテージか角度で指定できます。
例)red, yellow 50%, green
今回のホログラムの再現ではconic-gradient
の開始角度をデバイスの傾きと連動するように実装しました。
CodePenでは<input type="range">
で再現しました。
あとは、background-size
でサイズを指定すると良い感じになります。
さいごに
思いついたその日に実装したので少し粗雑な部分もありますが、何かの参考にしてもらえたら幸いです。
今回使用したDeviceOrientationEvent
の他にもDeviceMotionEvent
と言うデバイスの加速度を取得できるWeb APIもあるので他にも面白いものが作れたら記事を書きたいと思っています。
参考文献
Discussion