第一次尝试延迟加载(延迟加载嵌入的YouTube视频)——我怎样才能做得更优雅呢?

时间:2022-12-08 13:15:56

Yesterday I decided to improve the way my website loads YouTube videos by only embedding them when a user requests them. Sometimes a page could have as many as 30 videos on, and this would take a long time to load.

昨天我决定改进我的网站加载YouTube视频的方式,只在用户请求时嵌入它们。有时一个页面上可能有多达30个视频,这需要很长时间才能加载。

This is the first time I've attempted a "lazy loading" method of anything, and I figured it would be well worth asking:

这是我第一次尝试“延迟加载”的方法,我想这很值得一问:

What can I do to improve on this?

我能做些什么来改进它呢?

How can I make it a bit more graceful?

我怎样才能使它更优美呢?

Does this completely miss the point of deferred loading?

这是否完全忽略了延迟加载的要点?

JSFiddle.

JSFiddle。

Ignore the styling as that's irrelevant here.

忽略样式,因为这是不相关的。


The way this works is by first placing an anchor on the page containing the video's ID:

这种方法的方式是先在包含视频ID的页面上放置一个锚点:

<a href="#" data-video="FzRH3iTQPrk" class="youtube-video">

The jQuery behind then loops through every a.youtube-video and creates a transparent span with the video's thumbnail as its background:

后面的jQuery循环遍历每个a。youtube-video,创建一个透明的跨度,视频的缩略图作为背景:

$('a.youtube-video').each(function() {
    var videoId = $(this).attr('data-video');
    var videoThumbnail = "http://img.youtube.com/vi/" + videoId + "/0.jpg";

    var videoBackground = $('<span class="youtube-thumbnail"></span>');

    videoBackground.css({
        background:"#fff url('"+videoThumbnail+"') no-repeat"
    })
    ...

It then modifies the styling of the anchor tag (this is done here to prevent affecting browsers with JavaScript disabled):

然后修改锚标记的样式(这是为了防止影响浏览器的JavaScript禁用):

    $(this).css({
        height:315,
        width:460,
        position:"relative",
        display:"block",
        textAlign:"center",
        color:"#fff",
        fontSize:26
    });

It then finishes up the loop by adding the span to the anchor:

然后通过在锚点上增加跨度完成循环:

    $(this).text('Click to load video');
    $(this).append(videoBackground);
});

The loading of the embedded YouTube video object occurs on the anchor click:

嵌入YouTube视频对象的加载发生在锚点:

$('a.youtube-video').click(function(e) {
    e.preventDefault();
    var videoId = $(this).attr('data-video');
    var videoThumbnail = "http://img.youtube.com/vi/" + videoId + "/0.jpg";
    var videoEmbed = $('<object> ... </object>');      
        ...

This finishes up by adding the embed code to the anchor's parent and removing the anchor:

最后,将嵌入代码添加到锚的父节点,并删除锚节点:

    $(this).parent().append(videoEmbed);
    $(this).hide();
});

2 个解决方案

#1


4  

You should set the href so that people know what they're going to be loading. That can be done on the a element when the page is generated, or in JS. It has to be on the element if you want your page to work for people who have Javascript disabled.

你应该设置href,让人们知道他们要加载什么。这可以在生成页面时在元素a上完成,也可以在JS中完成。如果你想让你的页面为禁用了Javascript的人工作,它必须在元素上。

var url = "http://www.youtube.com/watch?v=" + videoId;
$(this).attr('href', url);

You should also tell people what will happen if they click either by setting a title:

你也应该告诉人们,如果他们点击一个标题,会发生什么:

$(this).attr('title', "Click to play video");

Or by creating an overlay like the ones at the SMH which makes it more obvious that clicking on the image will play a video. Or both.

或者像SMH那样创建一个覆盖层,这样点击图像就可以播放视频。或两者兼而有之。

Also you shouldn't break opening things in new window when people hold down ctrl or command key. I updated the fiddle but basically in your click event you need:

当人们按下ctrl或command键时,你也不应该在新窗口打开东西。我更新了小提琴,但基本上在你的点击事件中你需要:

 var isCtrlPressed = e.ctrlKey || e.metaKey;
 if (isCtrlPressed == true){
    return;
 } 

I know you said ignore the style, but I prefer it if a placeholder has a background color that is obviously different from the background of the page. If a page is slow loading, I can tell that something is going to load there, rather than it just being a blank bit of page.

我知道您说过忽略样式,但是我更喜欢如果一个占位符具有明显不同于页面背景的背景颜色。如果一个页面加载速度很慢,我可以判断它将在那里加载,而不是仅仅是一个空白的页面。

Does this completely miss the point of deferred loading?

这是否完全忽略了延迟加载的要点?

Not entirely but it is slightly pointless in this case. Deferred loading is usually used when the thing that is being loaded is very complex (e.g. a massive table) and so would add greatly to the page size, which would make the initial render of the page be a long time after the user followed the link.

不完全是,但在这种情况下,这有点毫无意义。延迟加载通常用于加载的东西非常复杂(例如一个大表格),因此会大大增加页面大小,这将使页面的初始呈现在用户跟随链接之后很长一段时间。

Although the youtube videos may be slow to load, they shouldn't actually block the rest of the page from loading and rendering in the meantime so deferring loading the videos only gives you a small benefit for quite a bit of work.

虽然youtube视频下载速度可能很慢,但它们不应该同时阻止页面的其他部分加载和呈现,因此延迟加载视频只会给你带来一点点好处,因为你需要做很多工作。

I guess you should measure how fast someone can view a page, scroll to the bottom and then click to play the last video. If it's faster with the deferred loading, because the other videos flash player isn't loaded then it could still be worth it.

我猜你应该测量一下人们浏览网页的速度,滚动到底部,然后点击播放上一个视频。如果延迟加载速度更快,因为其他视频flash播放器没有加载,那么它还是值得的。

#2


1  

There is a jsfiddle of the below code here. (The player doesn't show up correctly, I think jsfiddle doesn't work well with the "embed method". I know it works on jsfiddle using the iframe method but you mentioned you wanted to avoid iframes).

下面的代码有一个jsfiddle。(播放器显示不正确,我认为jsfiddle是“embed”。我知道它在使用iframe方法的jsfiddle是起作用的,但是您提到您希望避免使用iframe)。

One big improvement, as already mentioned, is to use swfobject to generate the player embed. When using this method, you must create a placeholder for the player element. The placeholder will be removed and replaced with the embed when the link is clicked. I highly recommend creating a parent div for the link and the player. In order to prevent resizing of elements when the embed is generating, you should also explicitly set the width/height of the container element.

如前所述,一个很大的改进是使用swfobject来生成播放器嵌入。使用此方法时,必须为player元素创建占位符。当单击链接时,占位符将被移除并替换为embed。我强烈建议为链接和播放器创建一个父div。为了防止在生成嵌入时调整元素的大小,还应该显式地设置容器元素的宽度/高度。

I think this is nice use of deferred loading. Although flash players don't block on load, they still use a lot of resources and I would appreciate a page that initially presents as a thumbnail set.

我认为这是延迟加载的好用法。虽然flash播放器不会阻塞负载,但它们仍然会使用大量的资源,我很欣赏一页最初呈现为缩略图的页面。

Markup

标记

<script src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js">
</script>

<div class="container">
    <div id="placeholder_FzRH3iTQPrk"></div>
    <a href="#" data-video="FzRH3iTQPrk" class="youtube-video"></a>
</div>
<div class="container">
    <div id="placeholder_go43XeW6Wg4"></div>
    <a href="#" data-video="go43XeW6Wg4" class="youtube-video"></a>
</div>

JavaScript

JavaScript

$(document).ready(function() {
    $('a.youtube-video').each(function() {
        var videoId = $(this).attr('data-video');
        var videoThumbnail = "http://img.youtube.com/vi/" + videoId + "/0.jpg";
        var videoBackground = $('<span class="youtube-thumbnail"></span>');
        videoBackground.css({
            background:"#fff url('"+videoThumbnail+"') no-repeat"
        });

        // also set the parent container size to prevent flicker
        $(this).add($(this).parent()).css({
            height:315,
            width:460,
            position:"relative",
            display:"block",
            textAlign:"center",
            color:"#fff",
            fontSize:26
        });
        $(this).text('Click to load video');
        $(this).append(videoBackground);
    });

    $('a.youtube-video').click(function(e) {
        e.preventDefault();
        var videoId = $(this).attr('data-video');
        var params = { allowScriptAccess: "always", allowFullScreen: "true" };
        var atts = { id: 'player_'+videoId };
        $(this).hide();
        swfobject.embedSWF(
            "http://www.youtube.com/v/"+videoId+"?enablejsapi=1&playerapiid=ytplayer&version=3", 
            'placeholder_'+videoId, "460", "315", "8", null, null, params, atts);

    });
});

#1


4  

You should set the href so that people know what they're going to be loading. That can be done on the a element when the page is generated, or in JS. It has to be on the element if you want your page to work for people who have Javascript disabled.

你应该设置href,让人们知道他们要加载什么。这可以在生成页面时在元素a上完成,也可以在JS中完成。如果你想让你的页面为禁用了Javascript的人工作,它必须在元素上。

var url = "http://www.youtube.com/watch?v=" + videoId;
$(this).attr('href', url);

You should also tell people what will happen if they click either by setting a title:

你也应该告诉人们,如果他们点击一个标题,会发生什么:

$(this).attr('title', "Click to play video");

Or by creating an overlay like the ones at the SMH which makes it more obvious that clicking on the image will play a video. Or both.

或者像SMH那样创建一个覆盖层,这样点击图像就可以播放视频。或两者兼而有之。

Also you shouldn't break opening things in new window when people hold down ctrl or command key. I updated the fiddle but basically in your click event you need:

当人们按下ctrl或command键时,你也不应该在新窗口打开东西。我更新了小提琴,但基本上在你的点击事件中你需要:

 var isCtrlPressed = e.ctrlKey || e.metaKey;
 if (isCtrlPressed == true){
    return;
 } 

I know you said ignore the style, but I prefer it if a placeholder has a background color that is obviously different from the background of the page. If a page is slow loading, I can tell that something is going to load there, rather than it just being a blank bit of page.

我知道您说过忽略样式,但是我更喜欢如果一个占位符具有明显不同于页面背景的背景颜色。如果一个页面加载速度很慢,我可以判断它将在那里加载,而不是仅仅是一个空白的页面。

Does this completely miss the point of deferred loading?

这是否完全忽略了延迟加载的要点?

Not entirely but it is slightly pointless in this case. Deferred loading is usually used when the thing that is being loaded is very complex (e.g. a massive table) and so would add greatly to the page size, which would make the initial render of the page be a long time after the user followed the link.

不完全是,但在这种情况下,这有点毫无意义。延迟加载通常用于加载的东西非常复杂(例如一个大表格),因此会大大增加页面大小,这将使页面的初始呈现在用户跟随链接之后很长一段时间。

Although the youtube videos may be slow to load, they shouldn't actually block the rest of the page from loading and rendering in the meantime so deferring loading the videos only gives you a small benefit for quite a bit of work.

虽然youtube视频下载速度可能很慢,但它们不应该同时阻止页面的其他部分加载和呈现,因此延迟加载视频只会给你带来一点点好处,因为你需要做很多工作。

I guess you should measure how fast someone can view a page, scroll to the bottom and then click to play the last video. If it's faster with the deferred loading, because the other videos flash player isn't loaded then it could still be worth it.

我猜你应该测量一下人们浏览网页的速度,滚动到底部,然后点击播放上一个视频。如果延迟加载速度更快,因为其他视频flash播放器没有加载,那么它还是值得的。

#2


1  

There is a jsfiddle of the below code here. (The player doesn't show up correctly, I think jsfiddle doesn't work well with the "embed method". I know it works on jsfiddle using the iframe method but you mentioned you wanted to avoid iframes).

下面的代码有一个jsfiddle。(播放器显示不正确,我认为jsfiddle是“embed”。我知道它在使用iframe方法的jsfiddle是起作用的,但是您提到您希望避免使用iframe)。

One big improvement, as already mentioned, is to use swfobject to generate the player embed. When using this method, you must create a placeholder for the player element. The placeholder will be removed and replaced with the embed when the link is clicked. I highly recommend creating a parent div for the link and the player. In order to prevent resizing of elements when the embed is generating, you should also explicitly set the width/height of the container element.

如前所述,一个很大的改进是使用swfobject来生成播放器嵌入。使用此方法时,必须为player元素创建占位符。当单击链接时,占位符将被移除并替换为embed。我强烈建议为链接和播放器创建一个父div。为了防止在生成嵌入时调整元素的大小,还应该显式地设置容器元素的宽度/高度。

I think this is nice use of deferred loading. Although flash players don't block on load, they still use a lot of resources and I would appreciate a page that initially presents as a thumbnail set.

我认为这是延迟加载的好用法。虽然flash播放器不会阻塞负载,但它们仍然会使用大量的资源,我很欣赏一页最初呈现为缩略图的页面。

Markup

标记

<script src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js">
</script>

<div class="container">
    <div id="placeholder_FzRH3iTQPrk"></div>
    <a href="#" data-video="FzRH3iTQPrk" class="youtube-video"></a>
</div>
<div class="container">
    <div id="placeholder_go43XeW6Wg4"></div>
    <a href="#" data-video="go43XeW6Wg4" class="youtube-video"></a>
</div>

JavaScript

JavaScript

$(document).ready(function() {
    $('a.youtube-video').each(function() {
        var videoId = $(this).attr('data-video');
        var videoThumbnail = "http://img.youtube.com/vi/" + videoId + "/0.jpg";
        var videoBackground = $('<span class="youtube-thumbnail"></span>');
        videoBackground.css({
            background:"#fff url('"+videoThumbnail+"') no-repeat"
        });

        // also set the parent container size to prevent flicker
        $(this).add($(this).parent()).css({
            height:315,
            width:460,
            position:"relative",
            display:"block",
            textAlign:"center",
            color:"#fff",
            fontSize:26
        });
        $(this).text('Click to load video');
        $(this).append(videoBackground);
    });

    $('a.youtube-video').click(function(e) {
        e.preventDefault();
        var videoId = $(this).attr('data-video');
        var params = { allowScriptAccess: "always", allowFullScreen: "true" };
        var atts = { id: 'player_'+videoId };
        $(this).hide();
        swfobject.embedSWF(
            "http://www.youtube.com/v/"+videoId+"?enablejsapi=1&playerapiid=ytplayer&version=3", 
            'placeholder_'+videoId, "460", "315", "8", null, null, params, atts);

    });
});