web-dev-qa-db-ja.com

YouTube iframe APIがYouTubeIframeAPIReadyでトリガーされない

私はかなり長い間、youtube iframe apiと戦っています。どういうわけか、メソッドonYouTubeIframeAPIReadyが常にトリガーされるわけではありません。

症状から、読み込みの問題のようです。インスペクターにエラーは表示されません。

ここに私のコードがあります:

HTML

<div id="player"></div>
          <script>
            videoId = 'someVideoId';
            var tag = document.createElement('script');
            tag.src = "//www.youtube.com/iframe_api";
            var firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
          </script>

JS

(ページの最後に呼び出されます。上記のスクリプトの直後にコードを配置しようとしましたが、結果は同じでした。)

var isReady = false
  , player
  , poster
  , video;

$(function () {
$('.js-play').click(function (e) {
    e.preventDefault();
    interval = setInterval(videoLoaded, 100);
  });
});
function onYouTubeIframeAPIReady() {
  console.log(videoId)
  player = new YT.Player('player', {
    height: '445',
    width: '810',
    videoId: videoId,
    events: {
      'onReady': onPlayerReady//,
      //'onStateChange': onPlayerStateChange
    }
  });
}

function onPlayerReady(event) {
  isReady = true;
  console.log("youtube says play")
}

function videoLoaded (){
  if (isReady) {
      console.log("ready and play")
      poster.hide();
      video.show();

      $('body').trigger('fluidvideos');

      player.playVideo();
      clearInterval(interval);
  } 
}

問題は、console.logによって何も印刷されず、何も起こらない場合があることです。

携帯電話では、これは常に発生します。何か案は?

37
jribeiro

これはタイムアウトの問題ではなく、この関数を手動で起動する必要はありません。

onYouTubeIframeAPIReady関数が、他の関数内でネスト(非表示)されていないグローバルレベルで使用可能であることを確認してください。

65
bcm

ウィンドウオブジェクトにいつでも追加して、グローバルに呼び出されるようにすることができます。これは、コードがAMDを使用している場合に役立ちます。

window.onYouTubeIframeAPIReady = function() {}
44
Erick R Soto

関数の内部に入れる必要がある場合、考えられる解決策の1つは次のとおりです。

_function onYouTubeIframeAPIReady() {
  // func body...
}
_

次のように宣言できます。

_window.onYouTubeIframeAPIReady = function() {
  // func body...
}
_

この場合、特定のスクリプトを宣言の後にdomに挿入するようにしてください(insertBefore()は、現在の場合、グローバルスコープにあるものを呼び出します)。

10
Pengő Dzsó

次のようにIFrame Player APIコードを非同期にロードする場合:

<script>
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
</script>

また、次のようなスクリプトコードもロードしています。

<script src="http://www.youtube.com/player_api"></script>

同じコードが2回ロードされるため、関数onYouTubeIframeAPIReadyは呼び出されません(APIが完全にロードされると、関数は1回だけ呼び出されます)。

したがって、ニーズに応じていずれかの方法を使用してください。

7
Joar

これを再検討した後、webpackを使用するとき(または他のcommongJSモジュールシステムを想定しているとき)、またはあなた自身のJSファイルの前にyoutube apiが準備できている場合、間隔を使用することでした-youtubeがいくつかを提供するまでpromiseコールバックの形式:

var checkYT = setInterval(function () {
    if(YT.loaded){
        //...setup video here using YT.Player()

        clearInterval(checkYT);
    }
}, 100);

私の場合、これが最もエラープルーフであるように見えました。

3
Joao

ローカルでロードするだけでなく、実際にWebでページを表示して、ページをテストしていることを確認してください。 YouTube iFrame APIの動作に一貫性がない/非決定的

3
Ben Wheeler

私も同様の問題を抱えていました。私の場合、onYouTubeIframeAPIReadyが非常に高速に呼び出されていたため、実際の実装では適切な呼び出しに対応できませんでした。 youtube player_apiを呼び出した後、onYouTubeIframeAPIReadyを検証するためのvarを使用した簡単な実装を追加しました。

<script src="http://www.youtube.com/player_api"></script>
<script>
var playerReady = false
window.onYouTubeIframeAPIReady = function() { //simple implementation
    playerReady = true;
}
</script>
</header>
.
.
.
<body>
<script>
window.onYouTubeIframeAPIReady = function() { //real and fully implemented
    var player; // ... and so on ...
}
if(playerReady) { onYouTubeIframeAPIReady(); console.log("force to call again") }
</script>
0
Diogo Garcia

実際にこれを作成して、YouTubeプレーヤーを遅延ロードしました。私には防弾のようです。

window.videoApiLoaded = [];
window.videoApiLoaded.youtube = false;

function loadYoutubeVideo(videoId) {

    window.onYouTubeIframeAPIReady = function() { document.dispatchEvent(new CustomEvent('onYouTubeIframeAPIReady', {})) };

    if(window.videoApiLoaded.youtube == false) {
        var tag = document.createElement('script');
        tag.src = "https://www.youtube.com/iframe_api";
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
        window.videoApiLoaded.youtube = true;
    }

    var player;

    document.addEventListener('onYouTubeIframeAPIReady', function (e) {
        player = new YT.Player('player', {
          height: '400',
          width: '600',
          videoId: videoId,
          events: {
            'onStateChange': onYtStateChange
          }
        });

    }, false);

}
0
Matt Loye