質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.00%

iPadで、フルスクリーンで表示されているビデオの中断時にページ遷移をしたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 5,597

JunzoMatunoo

score 27

動画を使ったブラウザアプリを作成しています。
iPad限定で使用するアプリで、動画解説ページの動画を再生するボタンをおした時に、display:none;で隠しておいたビデオをFullScreen APIを使って全画面表示をしてビデオを再生しています。

// 普段はビデオ要素を非表示にしておく
video {
  display: none;
}
var video = document.getElementsByTagName("video")[0];
video.webkitEnterFullScreen(); // フルスクリーン状態にして、
video.play(); // 再生

ここからが本題です。
ビデオの再生が完了したときに、下記の条件で別ページに遷移したいと思っています。

  • ビデオが最後まで再生され、自動的にフルスクリーンが解除された時・・・完了ページに移動する
  • ビデオを途中で中断してユーザーがフルスクリーンを解除した時・・・中断ページに移動する

これを実現しようと思い、videoのイベントを使って下記の様に設定してみました。

var video = document.getElementsByTagName("video")[0];
video.webkitEnterFullScreen(); // フルスクリーン状態にして、
video.play(); // 再生
video.addEventListener("ended", function (evt) {
  // ビデオの再生が完了した時に別のページに移動する
});

しかし、この書き方だと、動画が完全に再生されたあとしか発火せず、動画を途中で中断してフルスクリーン状態が解除された時には発火しないのです。

videoのイベントに動画を途中で中断したなんていうものは存在しないので、Full Screen APIのイベントであるfullscreenchangeイベントを使えばうまく設定できるかも、と思って下記のように書いてみました。

var video = document.getElementsByTagName("video")[0];
var video_state = "";

video.addEventListener("ended", function (evt) {
  video_state = "ended";
});

video.addEventListener("fullscreenchange", function (evt) {
  if (!evt.currentTarget.fullscreenEnabled && video_state == "") {
    // フルスクリーンが解除された時に、video_stateが空なら中断されたとみなして、
    //中断メッセージの書かれたページに移動
  } else if ( !evt.currentTarget.fullscreenEnabled $$ video_state == "ended" ) {
    // フルスクリーンが解除された時に、video_stateがendedなら、再生が完了しているとみなして、
    // 完了メッセージがかかれたページに移動
  }
});

video.webkitEnterFullScreen(); // フルスクリーン状態にして、
video.play(); // 再生

しかし、残念ながらfullscreenchangeイベントが発火せず行き詰ってしまいました。
webkitFullScreenと書いているように、まだベンダープレフィックスを付けないと行けないと思ってwebkitを付けてみて試してみましたが(webkitfullscreenchange,webkitFullScreenChange)それでもうまく行きませんでした。

色々と調べていると、Full Screen API自体がiOSに対応していないなんてことも書かれていたんですが、webkitFullScreenは動作するしで、よくわからん状態です><

確認環境は、MacのSimulatorを使ってiOS9.2で確認しています。

どなたかよい方法をご存知の方、ご教授願います。

 追記1:

MacのChromeではwebkitfullscreenchangeでうまくイベントが発火しました。。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

+1

kei344さんから頂いた回答をヒントにして下記のような形で解決できました。

// ビデオが最後まで再生された時
      video.addEventListener("ended", function (evt) {
        //ビデオが完全に終了した場合は、フルスクリーンを解除
        this.webkitExitFullScreen();
        console.log("ended");
        // 完了ページへの遷移を実行 ..
      });

      // ビデオが停止された時
      video.addEventListener('pause', function (evt) {
        // ビデオを停止時のスクリーンの状態を確認
        checkPausedState(this);
      });

      function checkPausedState (video) {

        setTimeout(function () {
          // videoのフルスクリーンモードを確認
          if (video.webkitDisplayingFullscreen) {
            // 動画が停止中か確認し、停止中なら再帰的に処理を実行
            if (video.paused) {
              console.log("full screen mode means still pausing..");
              checkPausedState(video);
            }
          } else {
            // フルスクリーンモードから抜けている場合はここを実行
            console.log("video playing canceled");
            // 中断ページへの遷移を実行 ..
          }
        }, 100);

      }

動画を中断する方法が、「"閉じる"ボタンを押して停止+フルスクリーン解除」と「"停止"を押したあとに"閉じる"を押してフルスクリーン解除」の2つがあって、pauseイベント発火時に必ずしもフルスクリーンが解除されている訳ではなかったので、setTimeout()で状態確認をして対応しました。

また、色々と調べていると、どうもiOS独自(?)のHTMLVideoElementなるものが存在するようで、webkitEnterFullScreen()webkitDisplayFullscreenはそのAPIが提供する機能です。
なので他デバイスでの実装にはAPIの実装状況をみて処理の切り替えが必要になりますが、今回はiPadのみ対象としていますので今回の実装はここまでにしときます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

手元に環境が無いため、できるかは試せていませんが、いくつか回答してみます。


  1. document.addEventListener( 'click', function(){} ) でタップ自体を取得し、そのとき再生中で無ければ中断している
    イベントの伝播がビデオでも問題なくいけるのであれば可能。
  2. ビデオの pause error abort などのイベントを監視する
    止まった状態でフルスクリーンかどうかを判別する。
  3. フルスクリーンが始まった時点で、背後で中断ページを読み込んでおく
    フルスクリーンを解除したら実質ページ移動したことと同じ意味合いになります。

何かのお役に立てればいいのですが・・・。

【html5 video 使う 再生中かどうかの判定 | 徳島のホームページ制作屋】
http://ziyudom.com/post-717/

【video要素、audio要素をJavaScriptから操作する-HTML5のAPI、および、関連仕様】
http://www.htmq.com/video/

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/12 03:17

    ありがとうございます!
    ご回答いただいた3つですが、

    1. → 再生中の動画の上でクリック(タップ)してみましたが、イベント伝播起こりませんでした。
    3. → このアプリですが、View側でriot.jsを使用していて(ソースコードはわかりやすくするため、その部分のコードは省いていました)、riot.routerによってhushChangeを監視している状態です。そのため、Viewを切り替えると、video要素も画面上からなくなってしまうのでこの方法は利用できませんでした。

    総合的に考えると、2の解決方法が良さそうな気がしましたので、その方向で考えてみます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.00%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる