動画再生中だけスライダーの自動スライドを止める

記事内に商品プロモーションを含む場合があります

Shopifyのテーマでよくスライダーに動画が設定できると思います。

今回は過去の案件で「自動でスライドさせて、動画が再生している間はスライダーの自動をとめる」ということをやりました。

その時は悩んでやっと実装できた記憶があるので、覚書としてブログに記録しておきます!

目次

コードだけ先に知りたい方はこちら

// 👇️ using noConflict mode
const $jq = jQuery.noConflict();

(()=>{
  let apiReadyResolve = null;
  let apiReady = null;

  function youtubeIframeAPIHelper_load() {
    if (apiReady) return apiReady;
    apiReady = new Promise(resolve => {
      apiReadyResolve = resolve;
    });

    if (window.onYouTubeIframeAPIReady) {
      // If onYouTubeIframeAPIReady is already defined, we need to call it
      const {
        onYouTubeIframeAPIReady
      } = window;

      window.onYouTubeIframeAPIReady = () => {
        onYouTubeIframeAPIReady();
        apiReadyResolve();
      };
    } else {
      window.onYouTubeIframeAPIReady = apiReadyResolve;
    }

    if (!document.querySelector('#youtube-api-script')) {
      const script = document.createElement('script');
      script.setAttribute('id', 'youtube-api-script');
      script.setAttribute('type', 'text/javascript');
      script.setAttribute('src', '<https://www.youtube.com/iframe_api>');
      document.body.appendChild(script);
    }

    if (window.YT && YT.loaded) {
      apiReadyResolve();
    }

    return apiReady;
  }

  //  load API then load Movies
  // =====================================
  window.addEventListener('load',()=>{

    youtubeIframeAPIHelper_load().then(startSlidermMovie());

  });

  const parentSlider = document.querySelector('.slideshow--viewport').getAttribute('id');

  const videoSlider = document.querySelectorAll('[data-video="youtube"]');

  let sliderplayer;
  let done = false;

  function startSlidermMovie(){
    videoSlider.forEach((item)=>{
      item.lastElementChild.remove();

      const player_id = 'slider-' + item.parentElement.getAttribute('data-slick-index');

      item.querySelector('.js-youtubeinner').setAttribute('id',player_id);
      const video_id = item.dataset.videoId;

      setTimeout(function(){
        sliderplayer = new YT.Player(player_id,{
          videoId: video_id,
          events: {
            'onStateChange': onPlayerStateChange
          }
        });
        item.classList.add('is-movie-loaded');
      },100);

      function onPlayerStateChange(event){
        if (event.data == YT.PlayerState.PLAYING) {
          pauseSlider();
        }
        if (event.data == YT.PlayerState.ENDED) {
          startSlider();
        }
      }

      function stopVideo() {
        sliderplayer.stopVideo();
      }

      $jq('.slideshow--viewport').on('afterChange',function(){
        stopVideo();
        $jq(this).slick('slickPlay');
      });

    });
  }

  function pauseSlider(){
    $jq('.slideshow--viewport').slick("slickPause");
  }
  function startSlider(){
    $jq('.slideshow--viewport').slick("slickPlay");
  }

  //  init Slider
  // ----------------------------------------
  $jq(function(){
    $jq(document).ready(function () {
      $jq(".slideshow--viewport").slick({
        infinite: true,
        autoplay: true,
        dots: true,
        autoplaySpeed: 2000,
        pauseOnHover: true,
        responsive: [
          {
            breakpoint: 600,
            settings: {
              arrows: false
            }
          },
        ]
      });
    });

  });

})();

コードの解説

前提条件

前提条件として今回は「Atlantic」というテーマを使いました。(2022年秋頃だったので、今はコードが若干違うかもです💦)

また、スライダーはSlickを使いました。

nonConflict modeを使用する

// 👇️ using noConflict mode
const $jq = jQuery.noConflict();

テーマに記載があったので、そのまま使ってましたが…

例えば複数のバージョンのjQueryを混在して使わなければならないような場合などに$関数だけではなく、jQueryオブジェクトも含めて完全にグローバルの名前空間から除去します。

つまり、

$(funtion(){
	// code...
});

を使えなくする、という意味ですね。

Youtube API を使って動画を再生する準備をする

このコードはYouTube IFrame Player API(YouTubeの動画をウェブページに埋め込むためのAPI)を扱うためのJavaScript関数です。この関数は、APIが準備完了するのを待って、その後の処理を行えるようにしています。

let apiReadyResolve = null; // YouTube APIの準備が完了したかどうか
let apiReady = null; // YouTube APIの準備が完了したかどうか
function youtubeIframeAPIHelper_load() {
  if (apiReady) return apiReady; // apiReadyがNULLじゃなかったら return

  apiReady = new Promise(resolve => {
    apiReadyResolve = resolve;
  });

  if (window.onYouTubeIframeAPIReady) {
    // If onYouTubeIframeAPIReady is already defined, we need to call it
    const {
      onYouTubeIframeAPIReady
    } = window;

    window.onYouTubeIframeAPIReady = () => {
      onYouTubeIframeAPIReady();
      apiReadyResolve();
    };
  } else {
    window.onYouTubeIframeAPIReady = apiReadyResolve;
  }

  if (!document.querySelector('#youtube-api-script')) {
    const script = document.createElement('script');
    script.setAttribute('id', 'youtube-api-script');
    script.setAttribute('type', 'text/javascript');
    script.setAttribute('src', '<https://www.youtube.com/iframe_api>');
    document.body.appendChild(script);
  }

	//もしYouTube APIが既にロードされていれば、Promiseをすぐに解決するためのチェック
  if (window.YT && YT.loaded) {
    apiReadyResolve();
  }

  return apiReady;
}


//  load API then load Movies
// =====================================
window.addEventListener('load',()=>{
 //読込完了したら、YouTubeAPIの読込確認し、終わり次第動画をスタートさせる
  youtubeIframeAPIHelper_load().then(startSlidermMvoie());

});

動画をスタートさせる関数


const parentSlider = document.querySelector('.slideshow--viewport').getAttribute('id');

const videoSlider = document.querySelectorAll('[data-video="youtube"]');

let sliderplayer;
let done = false;

function startSlidermMovie(){

  videoSlider.forEach((item)=>{
    item.lastElementChild.remove();

    const player_id = 'slider-' + item.parentElement.getAttribute('data-slick-index');

    item.querySelector('.js-youtubeinner').setAttribute('id',player_id);
    const video_id = item.dataset.videoId;

    setTimeout(function(){
      sliderplayer = new YT.Player(player_id,{
        videoId: video_id,
        events: {
          'onStateChange': onPlayerStateChange
        }
      });
      item.classList.add('is-movie-loaded'); // is-movie-loadedクラスを付与
    },100);

  });
}

[data-video="youtube"]という属性をもっているスライダーを取得し、YouTubeIDから動画を再生させるコードです。


function onPlayerStateChange(event){
	if (event.data == YT.PlayerState.PLAYING) {
 //動画再生中は スライダーを一時停止させる
	  pauseSlider();
	}
	if (event.data == YT.PlayerState.ENDED) {
 //動画再生終了したら、スライダーを再開させる
	  startSlider();
	}
}

上記コードで、YouTubeプレイヤーの状態が再生中か再生終了かで、再度自動スライドを開始したり、一時停止させています。

スライダーを初期化

.slideshow--viewport クラスをスライダーにします。

//  init Slider
  // ----------------------------------------
  $jq(function(){
    $jq(document).ready(function () {
      $jq(".slideshow--viewport").slick({
        infinite: true, //ループさせる
        autoplay: true, //自動再生
        dots: true, //ドットのナビゲーションあり
        autoplaySpeed: 2000, // 自動スライドのスピード
        pauseOnHover: true, //ホバーしたらスライドを一時停止させる
        responsive: [
				//レスポンシブの設定
          {
            breakpoint: 600,
            settings: {
              arrows: false
            }
          },
        ]
      });
    });

合わせて下記も関数として定義しておきます。


// スライダーを一時停止させる
function pauseSlider(){
  $jq('.slideshow--viewport').slick("slickPause");
}
// スライダーを再開させる
function startSlider(){
  $jq('.slideshow--viewport').slick("slickPlay");
}

また、スライダーを動かした後は動画再生を止め、自動スライドを再開させています。

function stopVideo() {
  sliderplayer.stopVideo();
}

$jq('.slideshow--viewport').on('afterChange',function(){
    stopVideo();
    $jq(this).slick('slickPlay');
  });

最後に

自動再生ありのスライダー+動画+動画再生中はスライドを止める、というよくありそうな仕様ですが、めちゃくちゃハマってしまったので備忘録として残しておきます…

参考になれば幸いです🙏

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

Shopify構築のカスタマイズ・代行を承っております。

目次