JQuery 加载 YouTube iframe 时效果卡顿

JQuery effect is stuttering when loading a YouTube iframe

我是 JS/JQuery/JQueryUI 的新手,但在我正在开发的新网站上做了一些工作。

我设置了一个基本的导航栏,其中 .click 使用 .show 使不同的 div 滑入视图,而其他三个使用 [=17= 弹出不存在].尽管这是超级基本的,但我为自己感到非常自豪。

我的问题是其中一个 div 包含 YouTube iframe。为了让它在显示另一个 div 时停止播放,我只是用 .attr 删除了 src(笨拙,我知道)。这意味着由于源每次都被重新附加到 iframe,回到那个 div 比我想要的要慢,并且 jQuery 结结巴巴。

我已将精简版放入 JSFiddle。非常感谢任何关于改进性能的建议!

PS: 我作为占位符的视频很搞笑,你应该喜欢它! :)

HTML:

<div class="button" id="home">1</div>
<div class="button" id="about">2</div>
<div class="button" id="latest">3</div>
<div class="button" id="contact">4</div>

<div class="home"><iframe class="video" id="homeVid"
    src="https://www.youtube.com/embed/gspaoaecNAg?controls=0?showinfo=0?rel=0?enablejsapi=1"
    frameborder="0" allowfullscreen></iframe></div>
<div class="content about"></div>
<div class="content latest"></div>
<div class="content contact"></div>

CSS

.content {
    width: 600px;
    height: 480px;
    display: none;
    clear:both
}

.home, .video {
    width: 600px;
    height: 480px;
    display: flex;
    clear:both;
    background-color: #CCC
}

.about {background-color: #F00}
.latest {background-color: #0F0}
.contact {background-color: #00F}

.button {
    width: 25px;
    height: 25px;
    border: 1px solid black
}

JavaScript

$(document).ready(function() {
    var urlhome = $('#homeVid').attr('src');
    $('#home').click(function() {
            $('.home').show('slide', {direction: 'right', easing: 'swing'}, 400);
            $('.about, .contact, .latest').hide(0);
            $('#homeVid').attr('src', urlhome);
    });
    $('#about').click(function() {
            $('.about').show('slide', {direction: 'right', easing: 'swing'}, 400);
            $('.home, .contact, .latest').hide(0);
            $('#homeVid').attr('src', ' ');
    });
    $('#latest').click(function() {
            $('.latest').show('slide', {direction: 'right', easing: 'swing'}, 400);
            $('.home, .contact, .about').hide(0);
            $('#homeVid').attr('src', ' ');
    });
    $('#contact').click(function() {
            $('.contact').show('slide', {direction: 'right', easing: 'swing'}, 400);
            $('.home, .about, .latest').hide(0);
            $('#homeVid').attr('src', ' ');
    });
});

的确,添加和删除 iframe 在性能方面成本很高。相反,我们必须停止播放并将其隐藏。

这需要使用 YouTube Player API Reference for iframe Embeds 以不同的方式将其插入到文档中。然后我们这样做:

HTML

<div class="content home">
    <div id="player"></div>
</div>
var player;

JavaScript

$(window).load(function(){

    player = new YT.Player('player', {
        height: '480',
        width: '600',
        videoId: 'gspaoaecNAg',
    });
});

只要隐藏 home 元素,我们就可以简单地使用 player.stopVideo();。但要是这么简单就好了。

使用 jQuery 的 hide() has side effects, because the way it hides elements is by setting their CSS to display:none which effectively removes them from the document. This destroys the iframe and recreates it on show(),它会出现与以前相同的性能问题。

我们需要一些更微妙的东西,通过将元素放在一边来隐藏它们。为此,我们使用定位:

.hidden {
    position:fixed;
    left:200%;
}

这会将它们放在文档的右侧,在视口之外,并且由于单位是相对的,因此无论我们将 window 拉伸多少,它都永远不会可见。这需要在 HTML 中进行一些更改,再加上一些其他的优化,我将在下面进一步详细说明。

HTML:

<div class="button" id="home">1</div>
<div class="button" id="about">2</div>
<div class="button" id="latest">3</div>
<div class="button" id="contact">4</div>

<div class="content home">
    <div id="player"></div>
</div>
<div class="content about hidden"></div>
<div class="content latest hidden"></div>
<div class="content contact hidden"></div>

我们已将 class hidden 添加到所有在开始时不可见的元素。我们还添加了一个 class 来描述元素本身,并设置为它们相应按钮的 id。我们在每个元素中都有 content class。

JavaScript:

var player;

$(window).load(function(){

    player = new YT.Player('player', {
        height: '480',
        width: '600',
        videoId: 'gspaoaecNAg',
    });
});

$(document).ready(function() {

    var all = $('.content');

    $('.button').click(function() {

        all.addClass('hidden');

        player.stopVideo();

        $('.'+this.id).animate({
            'left': '0px', 
            easing: 'swing'
        }, 400, function(){
            $(this).removeClass('hidden')
                .removeAttr('style');
        });
    });
});

这已经过优化以避免单独检查每个元素。第一部分之前已经解释过了,下面是剩下的部分:

  1. var all = $('.content');
    这 select 包含所有 .content 元素,并在变量 all 的回调外部引用它们,因此我们只需要在文档加载时执行一次。

  2. 我们在所有 button 元素上创建回调。下一步假定已收到点击事件。

  3. 我们将所有 .content 个元素设置为隐藏。实际上这应该只会影响当前未隐藏的那个。

  4. 我们停止播放视频。这只会影响嵌入的 iframe,我们不会费心检查哪个 .content 元素处于活动状态,因为停止已经停止的视频没有什么特别的。

  5. 使用触发click事件的按钮的id,我们select对应的.content元素。

  6. 我们替换show() with animate()并用它来修改classhidden中使用的CSS属性。这会将元素从隐藏位置滑动到正常位置。

  7. 动画完成后会执行回调。我们使用它首先从我们现在可见的元素中删除 hidden class,然后删除我们的动画设置 left:0px;style 属性,因为将它留在那里会稍后再干涉。

我们完成了。现在应该很顺利了。此 JSFiddle.

上提供了一个演示