Youtube iframe api non si triggers suYouTubeIframeAPIReady

Ho combattuto con l’iframe API di youtube per un bel po ‘di tempo. In qualche modo il metodo onYouTubeIframeAPIReady non viene sempre triggersto.

Dai sintomi sembra un problema di caricamento. Nessun errore è mostrato nell’ispettore.

Ecco il mio codice:

HTML

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

JS

(chiamato alla fine della pagina. Ho provato a inserire il codice subito dopo lo script sopra e il risultato è stato lo stesso.)

 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); } } 

Il problema è che a volte niente viene stampato da console.log e non succede nulla.

Sui telefoni cellulari questo succede sempre. Qualche idea?

Non si tratta di un problema di timeout e non è necessario triggersre questa funzione manualmente.

Assicurati che la funzione onYouTubeIframeAPIReady sia disponibile a livello globale, non nidificata (nascosta) all’interno di un’altra funzione.

Puoi sempre aggiungerlo all’object della finestra per assicurarti che venga evocato a livello globale. Questo è utile se il tuo codice sta usando amd.

 window.onYouTubeIframeAPIReady = function() {} 

Se devi mettere dentro una funzione, una soluzione ansible è invece di:

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

puoi dichiararlo così:

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

In questo caso, assicurati di inserire lo specifico script nella dom dopo la dichiarazione (la chiamata insertBefore() che cosa è nello scope globale ora nel tuo caso):

Se carichi il codice dell’IFrame Player API in modo asincrono come segue:

  

e stai anche caricando il codice dello script in questo modo:

  

quindi la funzione onYouTubeIframeAPIReady non verrà chiamata perché lo stesso codice viene caricato due volte (la funzione viene chiamata solo una volta quando l’API è completamente caricata).

Quindi usa solo uno dei modi in base alle tue esigenze.

Assicurati di testare la pagina facendola effettivamente pubblicare sul web, non solo caricata localmente. Il comportamento dell’API iFrame di YouTube è incoerente / non deterministico

Dopo aver rivisitato questo, ho trovato una soluzione di lavoro per me quando uso il webpack (o presumo qualsiasi altro sistema di moduli commongJS), o se trovi che l’apo di youtube è pronto prima del tuo file JS, doveva usare un intervallo – fino a quando youtube ne fornisce alcuni forma di callback di promise:

 var checkYT = setInterval(function () { if(YT.loaded){ //...setup video here using YT.Player() clearInterval(checkYT); } }, 100); 

Questo sembrava essere il più a prova di errore nel mio caso.

Ho avuto un problema simile, nel mio caso onYouTubeIframeAPIReady veniva chiamato così velocemente che l’implementazione effettiva non era pronta per la chiamata giusta. Quindi, dopo la chiamata a player_api di youtube ho aggiunto una semplice implementazione con una var per la verifica di onYouTubeIframeAPIReady proprio così:

    . . .   

In realtà ho fatto questo per caricare pigro il player di YouTube. Sembra a prova di proiettile per me.

 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); } 

Sono stato in grado di farlo funzionare in quasi tutte le circostanze con un semplice setTimeout sul caricamento della pagina. Non ideale, lo so, ma è solo un altro controllo che risolve il problema il più delle volte.

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