Подтвердить что ты не робот

Youtube iframe api не запускает onYouTubeIframeAPIReady

Я уже много лет сражаюсь с 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

(вызывается в конце страницы. Я попытался поместить код сразу после выше script, и результат был тем же.)

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, и ничего не происходит.

На мобильных телефонах это происходит постоянно. Любые идеи?

4b9b3361

Ответ 1

Это не проблема с таймаутом, и вам не нужно запускать эту функцию вручную.

Убедитесь, что ваша функция onYouTubeIframeAPIReady доступна на глобальном уровне, а не вложен (скрыта) в другой функции.

Ответ 2

Вы всегда можете присоединить его к объекту окна, чтобы убедиться, что он вызван глобально. Это полезно, если ваш код использует amd.

window.onYouTubeIframeAPIReady = function() {}

Ответ 3

Если вам нужно внести внутрь функцию, одно из возможных решений вместо:

function onYouTubeIframeAPIReady() {
  // func body...
}

вы можете объявить его следующим образом:

window.onYouTubeIframeAPIReady = function() {
  // func body...
}

В этом случае убедитесь, что вы вставляете определенный script в dom после объявления (вызов insertBefore(), который находится в глобальной области теперь в вашем случае):

Ответ 4

Если вы загрузите код API IFrame Player асинхронно следующим образом:

<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 следующим образом:

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

то функция onYouTubeIframeAPIReady не будет вызываться из-за того, что один и тот же код загружается дважды (функция вызывается только один раз, когда api полностью загружен).

Итак, используйте только один из способов в соответствии с вашими потребностями.

Ответ 6

После пересмотра этого вопроса, я нашел для меня рабочее решение при использовании webpack (или я предполагаю любую другую систему модулей commongJS), или если вы найдете, что apt YouTube готов до вашего собственного JS файла, нужно использовать интервал - до тех пор, пока youtube обеспечивает обратную связь с обещаниями:

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

        clearInterval(checkYT);
    }
}, 100);

В моем случае это было наиболее ошибочно.

Ответ 7

У меня была аналогичная проблема. В моем случае onYouTubeIframeAPIReady вызывался так быстро, что фактическая реализация не была готова для правильного вызова. Поэтому после вызова youtube player_api я добавил простую реализацию с var для проверки onYouTubeIframeAPIReady так:

<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>

Ответ 8

Я на самом деле сделал это для ленивой загрузки проигрывателя 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);

}

Ответ 9

Я смог выполнить эту работу практически во всех обстоятельствах с помощью простого setTimeout при загрузке страницы. Не знаю, я знаю, но это просто еще одна проверка, которая исправляет проблему большую часть времени.

setTimeout(function(){
    if (typeof(player) == 'undefined'){
        onYouTubeIframeAPIReady();
    }
}, 3000)