簡単なようで意外とハマってしまったのでまとめておく
やりたかったこと
- モーダルの枠一杯に動画を表示
- モーダルを開いて自動再生
- モーダルを閉じたら一時停止
- またモーダルを開いたら自動再生
実装したもの ※ElementUIを使ってモーダルを表示させています
<template lang="pug">
el-dialog(
:visible.sync="dialogVisible"
:before-close="hideDialog"
:title="title"
class="movie-dialog"
width="80%")
video(
:src="src"
@play="isPlaying = true"
@pause="isPlaying = false"
@canPlay="playMovie()"
@click="test"
controls
width="100%"
style="border: 2px solid #bababa"
)
</template>
<script lang="ts">
import { Vue, Prop, Component, Watch } from 'nuxt-property-decorator';
export default class MovieDialog extends Vue {
@Prop(Boolean) readonly dialogVisible!: boolean;
@Prop(String) readonly src!: string;
@Prop(String) readonly title!: string;
isPlaying = false;
@Watch('dialogVisible')
playMovie(): void {
const video = this.$el.querySelector('video');
if (video && this.dialogVisible) {
video.play();
}
}
pauseMovie(): void {
const video = this.$el.querySelector('video');
if (video) {
video.pause();
}
}
hideDialog(): void {
this.$emit('closeMovie');
this.pauseMovie();
}
なぜハマったか
取り敢えずググってみた
「Vue.js Videoタグ」で検索すると以下の記事が一番最初に出てくる.
https://kuranabe.hatenablog.com/entry/2018/09/20/211007
カスタムディレクティブを使うと楽とあるが、nuxt & typescriptでいい具合にカスタムディレクティブを書くには…こんな感じ?
import { Vue, Prop, Component, Directive } from 'nuxt-property-decorator';
中略
@Directive
playMovie()....
結果、Diretiveがいなくてエラー
カスタムディレクティブをNuxtで書く方法は?
調べたらこんな記事が
https://imatomix.com/imatomix/notes/1516891080
/plugins 以下にファイルを作成し、そこに記述する
追加したファイルを nuxt.config.jsに記述する
とはいえ、わざわざplug-inに差し込むのもなんかなぁ…コンポーネントだけで全部書いてしまいたい。
次の案:ディレクティブ使わずにiframeつかったら外部サイトのコントローラーとかもよしなについて来て良くね?
結果、iframeのWidthをパーセンテージで可変にした際に、Heightが追従しない。
超横長のiframeの中央で小さい動画が再生される始末…。
動画も縦横のサイズが必ずしも統一されるとは限らず、高さを指定するのが困難。
何よりも酷いのは、iframe内はコントロール不能で、モーダルを閉じてもずっと再生され続けているという事。
一度コンポーネントごと消すという事しないと駄目でかつ、モーダルを閉じるごとに最初から再生という地獄が…
原点回帰したら色々わかった
Videoタグの仕様を見てみる。
http://www.htmq.com/video/
知ったこと…
- videoタグにはいい具合のオプションが存在する
- autoplay : 自動再生
- controls : コントローラーを表示
video(autoplay controls src="...後略)
これだけで諸問題が色々解決される。
- videoタグには優れたイベントがあること
- play : 再生された時
- pause : 止まった時
- canplaythrough : いま再生を再開すれば、現在の再生レートで最後まで再生できて、途中でバッファリングのために停止することはないと推定される時
video(@play="isPlaying = true" @pause="isPlaying = false" ...後略)
みたいな書き方で、再生状態の取得も出来てしまう。美味しい!
困ったら、まずは仕様の確認というのは改めてやっておきたい。