在页面上为多个实例生成新的iframe YouTube播放器

时间:2020-06-29 17:55:24

标签: javascript youtube-api youtube-javascript-api youtube-iframe-api

当页面上只有一个YouTube视频实例时,以下JavaScript可以很好地发挥作用:

function createVideo(playerElement, videoID, autoplay=false) {
        const youtubeScriptId = 'youtube-api';
        const youtubeScript = document.getElementById(youtubeScriptId);

        if (youtubeScript === null) {
          const tag = document.createElement('script');
          const firstScript = document.getElementsByTagName('script')[0];

          tag.src = 'https://www.youtube.com/iframe_api';
          tag.id = youtubeScriptId;
          firstScript.parentNode.insertBefore(tag, firstScript);
        }

        window.onYouTubeIframeAPIReady = function() {
          return new window.YT.Player(playerElement, {
            videoId: videoID,
            playerVars: {
              autoplay: autoplay,
              modestbranding: 1,
              rel: 0
            }
          });
        }
      }

但是当我再次尝试调用此视频时,该视频无法加载。只有第一个视频。 在页面加载后通过click事件调用此方法,然后我传递一个videoID数据属性并构建新的YouTube视频以在页面上显示。

我假设是因为我的JavaScript在window对象上仅创建了一个实例,而不是将多个实例分开。经过进一步研究,我发现onYouTubeIframeAPIReady()方法仅在页面上触发一次,因此可以解释为什么单击事件触发此方法时后续调用失败。由于我无法知道页面上要加载多少个确切的实例,因此我将如何重构该代码以使其动态化,以便可以在页面unlimited instances上创建和播放via click events only?当您了解页面上的元素时,我已经看过无数有关构建YouTube视频的教程。但是在这种情况下,要么我不知道DOM上的内容是什么,要么想通过构建无限的YT视频(仅可能不会被用户单击播放而插入DOM)来减慢网站的页面加载速度。 >

是否甚至可以使用其与点击事件绑定的YT API在页面上动态创建新的YouTube视频?从我在网上阅读的内容来看,当YT API加载完成后,onYouTubeIframeAPIReady()首次加载到页面上时,人们似乎必须立即加载所有视频,而且我还必须添加额外的逻辑来播放/停止每个视频,然后将每个视频的其他点击事件绑定到显示/隐藏/播放/停止。这将大大增加我的页面负载,并在我的页面上添加一堆JS悬突。我只想在点击事件上创建一个新视频。

3 个答案:

答案 0 :(得分:0)

我希望您每次都不要使用相同的videoID,因为对于任何事物的多个实例,您都需要某种顺序的ID管理,例如...

var ID=[], Vid;


for(var i=0; i<20; i++){  // create 20 video players

 ID.push('V'+i);

 Vid=document.createElement('video');

 Vid.id=ID[i];

 document.body.appendChild(Vid);

 createVideo(e, ID[i], false);   // Your function

}

你得到了漂移...

答案 1 :(得分:0)

您遇到的核心问题是 YT.Player 只能在页面上初始化一次 - 如果您有多个视频要通过 YT.Player 处理,则必须逐个迭代视频一个具有相同的 YT.Player 实例。一开始有点奇怪,但可以工作 - 特别是如果您需要通过弹出模式等处理视频。

这是我用来迭代具有多个隐藏模式和视频的页面的示例,然后处理点击事件并播放视频:

jQuery(document).ready(function ($) {
    let modalTriggerElements = $('.video_play_icon'),
        playerInfoList = [],
        players = []

    if (typeof (YT) == 'undefined' || typeof (YT.Player) == 'undefined') {
        let tag = document.createElement('script'),
            firstScript = document.getElementsByTagName('script')[0]

        tag.src = 'https://www.youtube.com/iframe_api';
        tag.id = 'youtube-api';
        firstScript.parentNode.insertBefore(tag, firstScript)
    }

    if (modalTriggerElements.length > 0) {
        $.each(modalTriggerElements, (index, element) => {
            buildPlayersList(element)
            modalTriggerClickEvent(element)
        })
    }

    window.onYouTubePlayerAPIReady = function () {
        if (typeof playerInfoList === 'undefined') return;

        for (let i = 0; i < playerInfoList.length; i++) {
            players[i] = createPlayer(playerInfoList[i]);
        }
    }

    function createPlayer(playerInfo) {
        return new YT.Player(playerInfo.playerId, {
            videoId: playerInfo.videoId,
            playerVars: {
                showinfo: 0,
            }
        });
    }

    function buildPlayersList(element) {
        let $modelDiv = $(element).closest('.hc_module').next('.video_model'),
            $playerDiv = $($modelDiv).find('#video-player');

        playerInfoList.push({
            'videoId': $($modelDiv).data('video-id'),
            'playerId': $($playerDiv)[0],
        });
    }

    function modalTriggerClickEvent(element) {
        $(element).on('click', () => {
            let $parentDiv = $(element).closest('.hc_module'),
                $nearestVideoDiv = $parentDiv.next('.video_model'),
                $closeDiv = $nearestVideoDiv.find('.close_modal')

            $nearestVideoDiv.css('display', 'block')
            $nearestVideoDiv.attr('aria-hidden', 'false')

            $closeDiv.on('click', () => {
                $nearestVideoDiv.css('display', 'none')
                $nearestVideoDiv.attr('aria-hidden', 'true')

                players.forEach((el) => {
                    el.stopVideo();
                });
            })
        })
    }
});

答案 2 :(得分:-1)

当您不知道有多少玩家可以使用随机数来避免冲突时...

var ID=[];  // Global array


function AddVideoPlayer(){

var Vid, i=ID.length-1;

 ID.push('V'+RandomNumber(99999999)); 

 Vid=document.createElement('video');

 Vid.id=ID[i];

 document.body.appendChild(Vid);

 createVideo(e, ID[i], false);   // Your function

}