Je me bats avec l'ifi iframe youtube depuis un certain temps déjà. D'une manière ou d'une autre, la méthode onYouTubeIframeAPIReady
n'est pas toujours déclenchée.
D'après les symptômes, cela semble être un problème de chargement. Aucune erreur n'est affichée dans l'inspecteur.
Voici mon code:
<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>
(appelé à la fin de la page. J'ai essayé de placer le code juste après le script ci-dessus et le résultat était le même.)
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);
}
}
Le problème est que parfois, rien n’est imprimé par le console.log
et rien ne se passe.
Sur les téléphones mobiles, cela se produit tout le temps. Des idées?
Ce n'est pas un problème de délai d'attente, et vous ne devriez pas avoir besoin d'activer cette fonction manuellement.
Assurez-vous que votre fonction onYouTubeIframeAPIReady
est disponible au niveau global et non imbriquée (cachée) dans une autre fonction.
Vous pouvez toujours l'ajouter à l'objet window pour vous assurer qu'il est évoqué globalement. Ceci est utile si votre code utilise AMD.
window.onYouTubeIframeAPIReady = function() {}
Si vous devez intégrer une fonction, une solution possible est Au lieu de:
function onYouTubeIframeAPIReady() {
// func body...
}
vous pouvez le déclarer comme ceci:
window.onYouTubeIframeAPIReady = function() {
// func body...
}
Dans ce cas, assurez-vous d’insérer le script dans le dom après la déclaration (l’appel insertBefore()
appelle ce qui est dans la portée globale de votre cas):
Si vous chargez le code de l'API IFrame Player de manière asynchrone comme suit:
<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>
et vous chargez également le code de script comme ceci:
<script src="http://www.youtube.com/player_api"></script>
alors la fonction onYouTubeIframeAPIReady
ne sera pas appelée car le même code est chargé deux fois (la fonction est appelée une seule fois lorsque l'api est complètement chargé).
Utilisez donc l’un des moyens selon vos besoins.
Après avoir revisité cela, j’ai trouvé une solution qui me convenait lors de l’utilisation de webpack (ou de tout autre système de module commongJS). forme de promesse callback:
var checkYT = setInterval(function () {
if(YT.loaded){
//...setup video here using YT.Player()
clearInterval(checkYT);
}
}, 100);
Cela semblait être le plus sûr des erreurs dans mon cas.
Assurez-vous de tester la page en la faisant servir sur le Web, pas seulement chargée localement. Le comportement de l'API YouTube iFrame est incohérent/non déterministe
J'ai eu un problème similaire. Dans mon cas, YouTube a été appelé si rapidement que l'implémentation réelle n'était pas prête pour le bon appel. Donc, après l'appel de youtube player_api, j'ai ajouté une implémentation simple avec une variable permettant la vérification de onYouTubeIframeAPIReady juste comme ça:
<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>
J'ai en fait fait cela pour charger paresseux le lecteur youtube. Semble la preuve de balle pour moi.
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);
}