【Next.js】iOS端末でページ遷移時に音声を再生させる
はじめに
iOS端末にて、特定のページ遷移時に音声を再生させる必要がありました。iOS端末では自動再生に関するポリシーが存在するため、それを突破するための記事がたくさん存在します。(autoplay属性
が効かないためひと工夫必要になります。) 今回はその実装例を共有したいと思います。
方針
基本的に方針は他記事と同様です。
- 遷移前のイベント時に音声ファイルを
load()
する - 遷移先コンポーネントにて
play()
する
load()
する
今回は目的のページに遷移するための次へボタン
があるという前提で、そのボタンを押下したときにload()
する方針でいきたいと思います。
まず、音声ファイルを操作するためのインスタンスを作成したいと思います。今回はRecoil
を使用して状態として持ちたいと思います。(シンプルにグローバル変数とかで持つのもいいと思います。今回はグローバルに扱いたいものは状態で持つ方針だったので、音声ファイルについてもそのようにします。)
Audioコンストラクタはクライアント側で生成する必要があるので、typeof window !== 'undefined'
の条件を指定してあげます。(process.browser
でも問題ありませんが、deprecatedらしいです。)
Next.jsでAudioコンストラクタを呼ぶ方法は上記以外にも、next/dynamic
でssr:false
を指定してあげたり、useEffect内
で実行してあげることで実現できると思います。(useEffect内
で実行する方は試してないので怪しいですが...)
また、Next.jsでは画像や音声等静的ファイルは/public
下に配置し、以下のように指定してあげます。
const audioState = atom<HTMLAudioElement>({
key: "audio-state",
default: typeof window !== 'undefined'
? new Audio("/target-audio.mp4")
: undefined,
});
export const useAudio = () => {
const [audio, setAudio] = useRecoilState(audioState);
return { audio };
};
今回はatom
のdefaultにて初回にAudioインスタンスを生成していますが、fetchAudio()
のようなメソッドを作成して音声ファイルを入れ替えたりすることもできます。
次に、次へボタン
押下時にload()
してあげます。
const HomePage = () => {
const audioHooks = useAudio();
return (
<>
<h1>Home</h1>
<NextButton href="/next"
onClick={() => {
audioHooks.audio.load();
}}
Next
</NextButton>
</>
)
};
play()
する
あとは、NextPage()
内でplay()
してあげるだけです。
const NextPage = () => {
const audioHooks = useAudio();
audioHooks.audio?.play();
return (
<>
<h1>Next</h1>
</>
)
};
play()
メソッドを使用する時、NextPage()へ遷移後すぐに、再度前のページに遷移した場合、残りの音声が再生され続けてしまうため(例えば、音源が10s
あり、NextPage()
遷移後10s
以内に再度HomePage()
に戻った場合など)(単純にautoplayを使用するaudioタグであれば、遷移後は音声は止まってくれます)、先ほどのHomePage()
にてpause()
をしてあげます。
const HomePage = () => {
const audioHooks = useAudio();
+ audioHooks.audio?.pause()
以上です。ありがとうございました。
Discussion