¿Cómo pausar un reproductor de YouTube al ocultar el iframe?

86

Tengo un div oculto que contiene un video de YouTube en formato <iframe>. Cuando el usuario hace clic en un enlace, este div se vuelve visible, el usuario debería poder reproducir el video.

Cuando el usuario cierra el panel, el video debe detener la reproducción. ¿Cómo puedo conseguir esto?

Código:

<!-- link to open popupVid -->
<p><a href="javascript:;" onClick="document.getElementById('popupVid').style.display='';">Click here</a> to see my presenting showreel, to give you an idea of my style - usually described as authoritative, affable and and engaging.</p>

<!-- popup and contents -->
<div id="popupVid" style="position:absolute;left:0px;top:87px;width:500px;background-color:#D05F27;height:auto;display:none;z-index:200;">

  <iframe width="500" height="315" src="http://www.youtube.com/embed/T39hYJAwR40" frameborder="0" allowfullscreen></iframe>

  <br /><br /> 
  <a href="javascript:;" onClick="document.getElementById('popupVid').style.display='none';">
  close
  </a>
</div><!--end of popupVid -->
0161-Jon
fuente
No estoy seguro, pero es posible que tengas que encontrar una manera de detener el video o eliminar el video del div y no solo ocultarlo ..
aniri
deberías aceptar la respuesta.
snymkpr

Respuestas:

188

La forma más sencilla de implementar este comportamiento es llamando a los métodos pauseVideoy playVideo, cuando sea necesario. Inspirado por el resultado de mi respuesta anterior , escribí una función sin complementos para lograr el comportamiento deseado.

Los únicos ajustes:

  • He agregado una función, toggleVideo
  • He agregado ?enablejsapi=1a la URL de YouTube para habilitar la función.

Demostración: http://jsfiddle.net/ZcMkt/
Código:

<script>
function toggleVideo(state) {
    // if state == 'hide', hide. Else: show video
    var div = document.getElementById("popupVid");
    var iframe = div.getElementsByTagName("iframe")[0].contentWindow;
    div.style.display = state == 'hide' ? 'none' : '';
    func = state == 'hide' ? 'pauseVideo' : 'playVideo';
    iframe.postMessage('{"event":"command","func":"' + func + '","args":""}', '*');
}
</script>

<p><a href="javascript:;" onClick="toggleVideo();">Click here</a> to see my presenting showreel, to give you an idea of my style - usually described as authoritative, affable and and engaging.</p>

<!-- popup and contents -->
<div id="popupVid" style="position:absolute;left:0px;top:87px;width:500px;background-color:#D05F27;height:auto;display:none;z-index:200;">
   <iframe width="500" height="315" src="http://www.youtube.com/embed/T39hYJAwR40?enablejsapi=1" frameborder="0" allowfullscreen></iframe>
   <br /><br />
   <a href="javascript:;" onClick="toggleVideo('hide');">close</a>
Rob W
fuente
1
Sí, definitivamente necesitas la casilla de verificación verde si esto funcionó. También estoy tomando esta solución, excelente cosa, tengo estos fotogramas de video en un acordeón jQueryUI, así que necesito adjuntarlo a cada evento de activación.
jeffkee
Solo quería señalar que, lamentablemente, la API de YouTube te hace usar comillas dobles para el mensaje enviado a través de postMessage. No puede cambiar para tener comillas dobles externas y comillas simples internas, por ejemplo.
Jordania
1
@Jordan Eso tiene mucho sentido porque se espera que el mensaje sea JSON. JSON, por definición, utiliza comillas dobles para citar claves y valores.
Rob W
2
Si alguien está interesado, actualicé el código para detener la reproducción del video al hacer clic en el botón "Cerrar" en un modal de bootstrap 3. $ ("# MyModal-close") .click (function () {var div = document.getElementById ("MyModal-videoWrapper"); var iframe = div.getElementsByTagName ("iframe") [0] .contentWindow; iframe.postMessage ('{"evento": "comando", "func": "' + 'pauseVideo' + '", "args": ""}', '*');});
Ryan Walton
10
Tenga en cuenta que debe agregar el ?enablejsapi=1a la URL de incrustación de iframe de esta manera: <iframe class="embed-responsive-item" src="//www.youtube.com/embed/WIZUeIDFALw?html5=1&enablejsapi=1" allowfullscreen></iframe>o no funcionará :)
Dineth
23

Aquí hay una versión de jQuery de la respuesta de RobW para usar para ocultar / pausar un iframe en una ventana modal:

    function toggleVideo(state) {
        if(state == 'hide'){
            $('#video-div').modal('hide');
            document.getElementById('video-iframe'+id).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
        }
        else {
            $('#video-div').modal('show');
            document.getElementById('video-iframe'+id).contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
        }
    }

Los elementos html a los que se hace referencia son el div modal en sí (# video-div) que llama a los métodos show / hide, y el iframe (# video-iframe) que tiene la URL del video como es src = "" y tiene el sufijo enablejsapi = 1 ? que permite el control programático del reproductor (ej.

Para obtener más información sobre el html, consulte la respuesta de RobW.

Dibujó
fuente
5
¿Qué legibilidad mejorada estaba cambiando el? condicional a if / else pero gracias por iniciarme en esto. Sentí que tenía algo que agregar válido, eso es todo.
DrewT
15

Aquí hay un fragmento de jQuery simple para pausar todos los videos en la página según las respuestas de RobW y DrewT:

jQuery("iframe").each(function() {
  jQuery(this)[0].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*')
});
cuartario
fuente
si no desea usar jQuery, el código dentro de la función 'each' es el mismo después de quitar la referencia al objeto jQuery. es decir, node.contentWindow. ...
mattdlockyer
¿Cómo revierto esto para volver a reproducir cuando el video se muestra nuevamente?
Carl Papworth
Simplemente reemplace "pauseVideo" por "playVideo". Ejemplo: jsfiddle.net/ora2kqzq/1
quartarian
Eso ya no funciona ... incluso cuando lo intento, {"event":"command","func":"playVideo","args":[],"id":1,"channel":"widget"}después de lo {"event":"listening","id":1,"channel":"widget"}cual es lo que la API de iframe de YT.Player está publicando en YouTube Embed.
NoBugs
9

Oye, una manera fácil es simplemente configurar el src del video en nada, de modo que el video desaparezca mientras está oculto y luego configurar el src de nuevo al video que deseas cuando haces clic en el enlace que abre el video. que simplemente establece una identificación para el iframe de youtube y llama a la función src usando esa identificación de esta manera:

<script type="text/javascript">
function deleteVideo()
{
document.getElementById('VideoPlayer').src='';
}

function LoadVideo()
{
document.getElementById('VideoPlayer').src='http://www.youtube.com/embed/WHAT,EVER,YOUTUBE,VIDEO,YOU,WHANT';
}
</script>

<body>

<p onclick="LoadVideo()">LOAD VIDEO</P>
<p onclick="deleteVideo()">CLOSE</P>

<iframe id="VideoPlayer" width="853" height="480" src="http://www.youtube.com/WHAT,EVER,YOUTUBE,VIDEO,YOU,HAVE" frameborder="0" allowfullscreen></iframe>

</boby>
Paula
fuente
4
Advertencia: Las modificaciones a los iframe's srccon javascript se impulsarán inadvertidamente window.history, causando problemas con el botón Atrás.
Jordan Arseno
¡Gracias Jordan! Comencé a usar esta respuesta yo mismo y no estaba al tanto de este comportamiento. Es mejor saberlo ahora que después :)
MMachinegun
Advertencia justa para cualquiera que pruebe este método: puede causar un retraso extremadamente notable si lo usa para cambiar entre divs que contienen incrustaciones de iframe para YouTube. Ten cuidado.
Muhammad Abdul-Rahim
6

Dado que necesita establecer ?enablejsapi=trueel src del iframe antes de poder usar los comandos playVideo/ pauseVideomencionados en otras respuestas , podría ser útil agregar esto programáticamente a través de Javascript (especialmente si, por ejemplo, desea que este comportamiento se aplique a videos incrustados por otros usuarios que acaban de cortar y pegar un código de inserción de YouTube). En ese caso, algo como esto podría ser útil:

function initVideos() {

  // Find all video iframes on the page:
  var iframes = $(".video").find("iframe");

  // For each of them:
  for (var i = 0; i < iframes.length; i++) {
    // If "enablejsapi" is not set on the iframe's src, set it:
    if (iframes[i].src.indexOf("enablejsapi") === -1) {
      // ...check whether there is already a query string or not:
      // (ie. whether to prefix "enablejsapi" with a "?" or an "&")
      var prefix = (iframes[i].src.indexOf("?") === -1) ? "?" : "&amp;";
      iframes[i].src += prefix + "enablejsapi=true";
    }
  }
}

... si activa esto document.ready, todos los iframes en un div con una clase de "video" tendránenablejsapi=true agregado a su fuente, lo que permite que los comandos playVideo / pauseVideo funcionen en ellos.

(nb. este ejemplo usa jQuery para esa línea que establece var iframes, pero el enfoque general debería funcionar igual de bien con Javascript puro si no está usando jQuery).

Nick F
fuente
5

Puede detener el video llamando al stopVideo()método en la instancia del reproductor de YouTube antes de ocultar el div.

player.stopVideo()

Para obtener más detalles, consulte aquí: http://code.google.com/apis/youtube/js_api_reference.html#Playback_controls

david
fuente
¿Qué es el objeto del jugador y cómo se accede a él? Consigo el jugador no está definida y el vídeo todavía juega
Claudiu Creanga
Está disponible cuando creó una instancia con la API de JS.
David
4

La forma de RobW funcionó muy bien para mí. Para las personas que usan jQuery, aquí hay una versión simplificada que terminé usando:

var iframe = $(video_player_div).find('iframe');

var src = $(iframe).attr('src');      

$(iframe).attr('src', '').attr('src', src);

En este ejemplo, "video_player" es un div principal que contiene el iframe.

skribbz14
fuente
4

Quería compartir una solución que se me ocurrió al usar jQuery que funciona si tiene varios videos de YouTube incrustados en una sola página. En mi caso, he definido una ventana emergente modal para cada video de la siguiente manera:

<div id="videoModalXX">
...
    <button onclick="stopVideo(videoID);" type="button" class="close"></button>
    ...
    <iframe width="90%" height="400" src="//www.youtube-nocookie.com/embed/video_id?rel=0&enablejsapi=1&version=3" frameborder="0" allowfullscreen></iframe>
...
</div>

En este caso, videoModalXX representa una identificación única para el video. Luego, la siguiente función detiene el video:

function stopVideo(id)
{
    $("#videoModal" + id + " iframe")[0].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
}

Me gusta este enfoque porque mantiene el video en pausa donde lo dejó en caso de que quiera volver y continuar viendo más tarde. Funciona bien para mí porque busca el iframe dentro del modal de video con una identificación específica. No se requiere un ID de elemento de YouTube especial. Con suerte, a alguien también le resultará útil.

Poldon
fuente
Esto funcionó muy bien sin un montón de código. Tengo varios videos de YT en la página y solo muestra un pulgar de YT y necesitaba una solución de detención / pausa. Y al cambiar pauseVideo a playVideo, pude iniciar el video cuando se expandió al ancho de columna completo
WebDude0482
2

simplemente elimine src de iframe

$('button.close').click(function(){
    $('iframe').attr('src','');;
});
rakesh kejriwal
fuente
Pero es posible que desee continuar jugando cuando los usuarios hagan clic en abrir.
Coda Chang
hermano, al hacer clic nuevamente agregue src a través de jquery, funcionará
rakesh kejriwal
1

La respuesta de Rob W me ayudó a descubrir cómo pausar un video sobre iframe cuando un control deslizante está oculto. Sin embargo, necesitaba algunas modificaciones antes de que pudiera hacerlo funcionar. Aquí está un fragmento de mi html:

<div class="flexslider" style="height: 330px;">
  <ul class="slides">
    <li class="post-64"><img src="http://localhost/.../Banner_image.jpg"></li>
    <li class="post-65><img  src="http://localhost/..../banner_image_2.jpg "></li>
    <li class="post-67 ">
        <div class="fluid-width-video-wrapper ">
            <iframe frameborder="0 " allowfullscreen=" " src="//www.youtube.com/embed/video-ID?enablejsapi=1 " id="fitvid831673 "></iframe>
        </div>
    </li>
  </ul>
</div>

Observe que esto funciona en localhosts y también como Rob W mencionó, se agregó " enablejsapi = 1 " al final de la URL del video.

A continuación se muestra mi archivo JS:

jQuery(document).ready(function($){
    jQuery(".flexslider").click(function (e) {
        setTimeout(checkiframe, 1000); //Checking the DOM if iframe is hidden. Timer is used to wait for 1 second before checking the DOM if its updated

    });
});

function checkiframe(){
    var iframe_flag =jQuery("iframe").is(":visible"); //Flagging if iFrame is Visible
    console.log(iframe_flag);
    var tooglePlay=0;
    if (iframe_flag) {                                //If Visible then AutoPlaying the Video
        tooglePlay=1;
        setTimeout(toogleVideo, 1000);                //Also using timeout here
    }
    if (!iframe_flag) {     
        tooglePlay =0;
        setTimeout(toogleVideo('hide'), 1000);  
    }   
}

function toogleVideo(state) {
    var div = document.getElementsByTagName("iframe")[0].contentWindow;
    func = state == 'hide' ? 'pauseVideo' : 'playVideo';
    div.postMessage('{"event":"command","func":"' + func + '","args":""}', '*');
}; 

Además, como un ejemplo más simple, mira esto en JSFiddle

Fahim Hossain
fuente
1

Este enfoque requiere jQuery. Primero, seleccione su iframe:

var yourIframe = $('iframe#yourId');
//yourId or something to select your iframe.

Ahora selecciona el botón reproducir / pausa de este iframe y hacer clic en él

$('button.ytp-play-button.ytp-button', yourIframe).click();

Espero que te ayude.

hong4rc
fuente
0

Las respuestas de RobW aquí y en otros lugares fueron muy útiles, pero descubrí que mis necesidades eran mucho más simples. He respondido esto en otro lugar , pero quizás también sea útil aquí.

Tengo un método en el que formo una cadena HTML para cargarla en un UIWebView:

NSString *urlString = [NSString stringWithFormat:@"https://www.youtube.com/embed/%@",videoID];

preparedHTML = [NSString stringWithFormat:@"<html><body style='background:none; text-align:center;'><script type='text/javascript' src='http://www.youtube.com/iframe_api'></script><script type='text/javascript'>var player; function onYouTubeIframeAPIReady(){player=new YT.Player('player')}</script><iframe id='player' class='youtube-player' type='text/html' width='%f' height='%f' src='%@?rel=0&showinfo=0&enablejsapi=1' style='text-align:center; border: 6px solid; border-radius:5px; background-color:transparent;' rel=nofollow allowfullscreen></iframe></body></html>", 628.0f, 352.0f, urlString];

Puede ignorar las cosas de estilo en la cadena de HTML preparado. Los aspectos importantes son:

  • Usando la API para crear el objeto "YT.player". En un momento, solo tenía el video en la etiqueta iFrame y eso me impidió hacer referencia al objeto "reproductor" más tarde con JS.
  • He visto algunos ejemplos en la web donde se omite la primera etiqueta de secuencia de comandos (la que tiene la etiqueta iframe_api src), pero definitivamente lo necesitaba para que esto funcionara.
  • Creando la variable "player" al principio del script API. También he visto algunos ejemplos que han omitido esa línea.
  • Agregar una etiqueta de identificación al iFrame para que se haga referencia en el script de API. Casi me olvido de esa parte.
  • Añadiendo "enablejsapi = 1" al final de la etiqueta iFrame src. Eso me colgó por un tiempo, ya que inicialmente lo tenía como un atributo de la etiqueta iFrame, que no funciona / no funcionó para mí.

Cuando necesito pausar el video, simplemente ejecuto esto:

[webView stringByEvaluatingJavaScriptFromString:@"player.pauseVideo();"];

¡Espero que ayude!

Brian
fuente
En caso de que se esté preguntando por qué no hay votos positivos, es porque no es javascript, por lo que no es útil para el caso de uso del OP, que es un iframe que hace referencia a una URL de inserción de YouTube, no a una aplicación de iOS.
Vroo
@Vroo Sí, lo entiendo. Solo quería dejar esta respuesta aquí en caso de que otra persona de iOS viniera aquí y encontrara esta pregunta como yo.
Brian
0

Esto me funciona bien con el reproductor de YouTube.

 createPlayer(): void {
  return new window['YT'].Player(this.youtube.playerId, {
  height: this.youtube.playerHeight,
  width: this.youtube.playerWidth,
  playerVars: {
    rel: 0,
    showinfo: 0
  }
});
}

this.youtube.player.pauseVideo ();

HuyLe
fuente
0

Una respuesta más concisa, elegante y segura: agregue "? Enablejsapi = 1" al final de la URL del video, luego construya y cadena un objeto ordinario que represente el comando de pausa:

const YouTube_pause_video_command_JSON = JSON.stringify(Object.create(null, {
    "event": {
        "value": "command",
        "enumerable": true
    },
    "func": {
        "value": "pauseVideo",
        "enumerable": true
    }
}));

Use el Window.postMessagemétodo para enviar la cadena JSON resultante al documento de video incrustado:

// |iframe_element| is defined elsewhere.
const video_URL = iframe_element.getAttributeNS(null, "src");
iframe_element.contentWindow.postMessage(YouTube_pause_video_command_JSON, video_URL);

Asegúrese de especificar la URL del video para el argumento Window.postMessagedel método targetOriginpara asegurarse de que sus mensajes no se envíen a ningún destinatario no deseado.

Patrick Dark
fuente