jquery Youtube を Lightbox のようなモーダルウィンドウで表示

2014年2月7日

Youtube の映像をプラグインを使わずに Lightbox のようなモーダルウィンドウで表示しようと試した際の失敗例。結果的にはプラグインを使用することにしたが、後日何か別の方法が見つかればその際の参考にするためのメモ。

概要

Firefox では問題なく表示・再生できたが、それ以外のブラウザでは以下のような問題が発生。

  • 「停止ボタン」を押さずにモーダルウィンドウを閉じてしまうと音がそのまま鳴り続ける(IEなど)
  • 「停止ボタン」をクリックしても映像は止まるが音が止まらない(Chromeなど)
  • IE の Safari ではモーダルウィンドウを閉じても、映像も消えない

いろいろと試したところ、iframe を remove() することで音が止まるようになった。但し、一時停止(ポーズ)ボタンをクリックしても映像は止まるが音が止まらないのは、未解決。モーダルウィンドウを閉じると音も止まるが。。。

結論

実用的ではないので、プラグインを探してみたらいいものが見つかったのでそれを使用。

関連ページ:「Magnific Popup を使って見る

取りあえずモーダルウィンドウで表示してみる

サンプル1

画像をクリックすると、Youtube を表示するようにする。

  • クラス名が「video_image」の div 要素に画像と Youtube の src を記述して、 src が記述してある div 要素(クラス名:video_info)を非表示に
  • モーダルウィンドウで表示する際にはクラス名が「top_video」の div 要素(最初は非表示)の内容を表示する

HTML

<div class="video_image">
    <img src="images/jimpat.jpg" alt="Youtube">
    <div class="video_info">
        <span class="video_src">//www.youtube.com/embed/wuaD9yG4Fdw</span>
    </div><!--end of .video_info-->
</div><!--end of .video_image-->
    
<div class="video_image">
    <img src="images/wes.jpg" alt="Youtube">
    <div class="video_info">
        <span class="video_src">//www.youtube.com/embed/hLWlqBH9nrU</span>
    </div><!--end of .video_info-->
</div><!--end of .video_image-->
       
<div id="top_video" >   
    <div class="youtube">
        <iframe id="player" src="" frameborder="0" allowfullscreen></iframe>
    </div><!--end of .youtube-->
    <div id="close_link">
        <p><a href="#"> 閉じる </a></p>
    </div><!--end of #video_link-->
</div><!--end of #top_video-->

iframe はブラウザのサイズにより可変に。

CSS

#graylayer {
  display: none;
  position: fixed;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  background: #666;
  filter:alpha(opacity=75);
  opacity: 0.75;
  z-index: 200;
}
* html #graylayer {
  position: absolute;
}
#overlayer {
  display: none;
  width: 80%;
  background: #111;
  padding: 1em;
  border: 2px solid #CCC;
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 300;
  height: 90%;
  overflow: scroll;
}

* html #overlayer {
  position: absolute;
}

#overlayer button.close {
  position: absolute;
  top: 10px;
  right: 10px;
}
.youtube {
    position: relative;
    padding-bottom: 56.25%;
    padding-top: 60px;
    height: 0;
    overflow: hidden;
    margin-top: 3.25%;
    margin-bottom: 3.25%;
}
#top_video{
  display: none;
}
.youtube iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
#top_video .youtube iframe {
  max-width: 600px;
  max-height: 450px;
}

jQuery

jQuery(function($){

  $('body').append('<div id="graylayer"></div><div id="overlayer"></div>');

  function lightBox(target) {
    $('#overlayer').data('scroll_top', $(window).scrollTop());
    $('#graylayer').fadeIn();    
    $('#overlayer').fadeIn().html(target).css({
      marginTop: "-" + $('#overlayer').height()/2 + "px",
      marginLeft: "-" + $('#overlayer').width()/2 + "px"
    });
  }
  
  $('#graylayer').click(function(){
    $(this).fadeOut();
    $('#overlayer').fadeOut();
  });
  
  $(document).on('click', '#close_link a', function() {
    $('#graylayer').fadeOut();
    $('#overlayer').fadeOut();
    return false;
  });  

  $('.video_image img').click(function(){
    $('.youtube iframe').attr('src', $.trim($(this).closest('.video_image').find('.video_info span.video_src').text()) + '?autoplay=1&rel=0');
    lightBox($('#top_video').html());
    return false;
  });
  
});

閉じる際に iframe を remove() する

サンプル2

モーダルウィンドウを表示する度に、iframe を追加し、閉じる際に削除するようにしてみる。そのため HTML では、iframe の部分を削除して jQuery で追加・削除するようにする。

これで閉じる際には、音も消えるようになったが、Chrome や Safari では「停止ボタン」をクリックしても、音が止まらないのは解決できていない。(実用的には無理)

HTML

<div id="top_video" >   
    <div class="youtube">
        <!-- 削除 <iframe id="player" src="" frameborder="0" allowfullscreen></iframe>-->
    </div><!--end of .youtube-->
    <div id="close_link">
        <p><a href="#"> 閉じる </a></p>
    </div><!--end of #video_link-->
</div><!--end of #top_video-->

jQuery では閉じるたびに、remove() する。但し、何故かはわからないが2回実行しないとうまく削除できない。

jQuery(function($){

  $('body').append('<div id="graylayer"></div><div id="overlayer"></div>');

  function lightBox(target) {
    $('#overlayer').data('scroll_top', $(window).scrollTop());
    $('#graylayer').fadeIn();    
    $('#overlayer').fadeIn().html(target).css({
      marginTop: "-" + $('#overlayer').height()/2 + "px",
      marginLeft: "-" + $('#overlayer').width()/2 + "px"
    });
  }
  
  $('#graylayer').click(function(){
    if($('#player').length > 0){
      // iframe を削除(2回)
      $('#player').remove();
      $('#player').remove();
    }
    $(this).fadeOut();
    $('#overlayer').fadeOut();
  });
  
  $(document).on('click', '#close_link a', function() {
    if($('#player').length > 0){
      // iframe を削除(2回)
      $('#player').remove();
      $('#player').remove();
    }
    $('#graylayer').fadeOut();
    $('#overlayer').fadeOut();
    return false;
  });  

  $('.video_image img').click(function(){
    // iframe を追加
    $('#top_video .youtube').prepend('<iframe id="player" src="" frameborder="0" allowfullscreen></iframe>');
    $('.youtube iframe').attr('src', $.trim($(this).closest('.video_image').find('.video_info span.video_src').text()) + '?autoplay=1&rel=0');
    lightBox($('#top_video').html());
    return false;
  });
  
});

IFrame player API

IFrame player API を使って何とかならないかと試したが、いい方法が見つからなかった。

以下は IFrame player API を使って通常に Youtube を表示して、独自の「停止ボタン」を追加した例。

サンプル3

HTML

<div id="player"></div>
<p><a id="stop" href="#">Stop</a></p>

jQuery

var player;
var stopBtn = $('#stop');

//IFrame player API を使うための JavaScript の読み込み
var scriptTag = document.createElement('script');
scriptTag.src = "https://www.youtube.com/player_api";
var fsTag = document.getElementsByTagName('script')[0];
fsTag.parentNode.insertBefore(scriptTag, fsTag);

var vid = 'wuaD9yG4Fdw';

// API のスクリプトが読み込まれたら <iframe> (and YouTube player) を作成する function
function onYouTubePlayerAPIReady() {
  player = new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: vid,
    playerVars: {
      autohide: 2, //コントローラーを常に表示
      controls: 1, //コントローラーを表示(デフォルト)
      autoplay: 1,  //自動再生する
      rel: 0 //再生終了後に関連動画を表示しない

    }
  });
  stopBtn.click(function(){
    player.stopVideo();
  });
}