Fiddle Links: Kod źródłowy - Podgląd - Mała wersja
Aktualizacja: Ta mała funkcja wykonuje kod tylko w jednym kierunku. Jeśli chcesz mieć pełne wsparcie (np. Nasłuchujący / pobierający zdarzenia), spójrz na Listening for Youtube Event w jQuery
W wyniku dogłębnej analizy kodu utworzyłem funkcję: function callPlayer
żąda wywołania funkcji w dowolnym obramowanym filmie YouTube. Zobacz odniesienie do interfejsu API YouTube, aby uzyskać pełną listę możliwych wywołań funkcji. Przeczytaj komentarze w kodzie źródłowym, aby uzyskać wyjaśnienie.
17 maja 2012 r. Podwojono rozmiar kodu, aby zadbać o stan gotowości gracza. Jeśli potrzebujesz kompaktowej funkcji, która nie radzi sobie ze stanem gotowości odtwarzacza, zobacz http://jsfiddle.net/8R5y6/ .
/**
* @author Rob W <gwnRob@gmail.com>
* @website https://stackoverflow.com/a/7513356/938089
* @version 20190409
* @description Executes function on a framed YouTube video (see website link)
* For a full list of possible functions, see:
* https://developers.google.com/youtube/js_api_reference
* @param String frame_id The id of (the div containing) the frame
* @param String func Desired function to call, eg. "playVideo"
* (Function) Function to call when the player is ready.
* @param Array args (optional) List of arguments to pass to function func*/
function callPlayer(frame_id, func, args) {
if (window.jQuery && frame_id instanceof jQuery) frame_id = frame_id.get(0).id;
var iframe = document.getElementById(frame_id);
if (iframe && iframe.tagName.toUpperCase() != 'IFRAME') {
iframe = iframe.getElementsByTagName('iframe')[0];
}
// When the player is not ready yet, add the event to a queue
// Each frame_id is associated with an own queue.
// Each queue has three possible states:
// undefined = uninitialised / array = queue / .ready=true = ready
if (!callPlayer.queue) callPlayer.queue = {};
var queue = callPlayer.queue[frame_id],
domReady = document.readyState == 'complete';
if (domReady && !iframe) {
// DOM is ready and iframe does not exist. Log a message
window.console && console.log('callPlayer: Frame not found; id=' + frame_id);
if (queue) clearInterval(queue.poller);
} else if (func === 'listening') {
// Sending the "listener" message to the frame, to request status updates
if (iframe && iframe.contentWindow) {
func = '{"event":"listening","id":' + JSON.stringify(''+frame_id) + '}';
iframe.contentWindow.postMessage(func, '*');
}
} else if ((!queue || !queue.ready) && (
!domReady ||
iframe && !iframe.contentWindow ||
typeof func === 'function')) {
if (!queue) queue = callPlayer.queue[frame_id] = [];
queue.push([func, args]);
if (!('poller' in queue)) {
// keep polling until the document and frame is ready
queue.poller = setInterval(function() {
callPlayer(frame_id, 'listening');
}, 250);
// Add a global "message" event listener, to catch status updates:
messageEvent(1, function runOnceReady(e) {
if (!iframe) {
iframe = document.getElementById(frame_id);
if (!iframe) return;
if (iframe.tagName.toUpperCase() != 'IFRAME') {
iframe = iframe.getElementsByTagName('iframe')[0];
if (!iframe) return;
}
}
if (e.source === iframe.contentWindow) {
// Assume that the player is ready if we receive a
// message from the iframe
clearInterval(queue.poller);
queue.ready = true;
messageEvent(0, runOnceReady);
// .. and release the queue:
while (tmp = queue.shift()) {
callPlayer(frame_id, tmp[0], tmp[1]);
}
}
}, false);
}
} else if (iframe && iframe.contentWindow) {
// When a function is supplied, just call it (like "onYouTubePlayerReady")
if (func.call) return func();
// Frame exists, send message
iframe.contentWindow.postMessage(JSON.stringify({
"event": "command",
"func": func,
"args": args || [],
"id": frame_id
}), "*");
}
/* IE8 does not support addEventListener... */
function messageEvent(add, listener) {
var w3 = add ? window.addEventListener : window.removeEventListener;
w3 ?
w3('message', listener, !1)
:
(add ? window.attachEvent : window.detachEvent)('onmessage', listener);
}
}
Stosowanie:
callPlayer("whateverID", function() {
// This function runs once the player is ready ("onYouTubePlayerReady")
callPlayer("whateverID", "playVideo");
});
// When the player is not ready yet, the function will be queued.
// When the iframe cannot be found, a message is logged in the console.
callPlayer("whateverID", "playVideo");
Możliwe pytania (i odpowiedzi):
P : To nie działa!
Odp . : „Nie działa” nie jest jasnym opisem. Czy otrzymujesz komunikaty o błędach? Proszę pokazać odpowiedni kod.
P : playVideo
nie odtwarza wideo.
O : Odtwarzanie wymaga interakcji użytkownika i obecności allow="autoplay"
w elemencie iframe. Zobacz https://developers.google.com/web/updates/2017/09/autoplay-policy-changes i https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide
P : Osadziłem film z YouTube za pomocą, <iframe src="http://www.youtube.com/embed/As2rZGPGKDY" />
ale ta funkcja nie wykonuje żadnej funkcji! : Trzeba dodać na końcu adresu URL: .
?enablejsapi=1
/embed/vid_id?enablejsapi=1
P : Otrzymuję komunikat o błędzie „Określono nieprawidłowy lub niedozwolony ciąg znaków”. Czemu?
Odp . : API nie działa poprawnie na lokalnym hoście ( file://
). Hostuj swoją (testową) stronę online lub użyj JSFiddle . Przykłady: Zobacz linki u góry tej odpowiedzi.
P : Skąd o tym wiedziałeś?
Odp . : Spędziłem trochę czasu, aby ręcznie zinterpretować źródło API. Doszedłem do wniosku, że muszę użyć tej postMessage
metody. Aby wiedzieć, które argumenty przekazać, stworzyłem rozszerzenie Chrome, które przechwytuje wiadomości. Kod źródłowy rozszerzenia można pobrać tutaj .
P : Jakie przeglądarki są obsługiwane?
O : Każda przeglądarka obsługująca JSON i postMessage
.
- IE 8+
- Firefox 3.6+ (właściwie 3.5, ale
document.readyState
został zaimplementowany w 3.6)
- Opera 10.50+
- Safari 4+
- Chrome 3+
Powiązana odpowiedź / implementacja: Zanikaj oprawione wideo za pomocą jQuery
Pełna obsługa interfejsu API: Słuchanie wydarzenia YouTube w jQuery
Oficjalny interfejs API: https://developers.google.com/youtube/iframe_api_reference
Historia zmian
- 17 may 2012
Zaimplementowane onYouTubePlayerReady
: callPlayer('frame_id', function() { ... })
.
Funkcje są automatycznie umieszczane w kolejce, gdy gracz nie jest jeszcze gotowy.
- 24 lipca 2012
Zaktualizowano i pomyślnie przetestowano w obsługiwanych przeglądarkach (patrz w przyszłość).
- 10 października 2013 Przekazanie funkcji jako argument
callPlayer
wymusza sprawdzenie gotowości. Jest to potrzebne, ponieważ gdy callPlayer
jest wywoływane zaraz po wstawieniu elementu iframe, gdy dokument jest gotowy, nie może wiedzieć na pewno, że element iframe jest w pełni gotowy. W przeglądarkach Internet Explorer i Firefox ten scenariusz spowodował zbyt wczesne wywołanie programu postMessage
, które zostało zignorowane.
- 12 grudnia 2013, zaleca się dodanie
&origin=*
adresu URL.
- 2 marca 2014 r. Wycofano rekomendację usunięcia
&origin=*
do adresu URL.
- 9 kwietnia 2019, napraw błąd, który powodował nieskończoną rekursję, gdy YouTube ładuje się, zanim strona była gotowa. Dodaj notatkę o autoodtwarzaniu.