Загрузка видео по требованию пользователя

Загрузка видео по требованию пользователя

Всем привет! Как известно, чем больше весит страница, тем медленнее она открывается. Особенно это касается страниц в которых встроено видео с популярных видеохостингов. Представьте ситуацию, когда Вы открываете сайт для прочтения текстовой информации, но вместо этого ждете несколько секунд, пока загрузится видео.

Не очень приятная ситуация. Поэтому логично сделать загрузку видео только по требованию пользователя. Для этого мы напишем плагин для загрузки видео по клику на превью.

Содержание статьи:

Постановка проблемы и тесты

При решении какой-то проблемы, нужно понять, насколько эта проблема серьезная и нуждается ли вообще эта проблема в решении.

Для тестов я создал самую обычную html страничку, в которую поместил код загрузки видео:

html
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v1</title>
</head>
<body>
<iframe width="560" height="315" src="https://www.youtube.com/embed/CpAcxbtXUgQ" frameborder="0" allowfullscreen></iframe>
</body>
</html>

И заглянул в консоль браузера, во вкладку network:

1.jpg

Как видим, загрузка страницы длится 2,09s, что мягко говоря, не быстро.

Затем я решил, что условия слишком идеальны и неплохо бы проверить скорость загрузки, если на страницу добавить несколько популярных библиотек: jquery, jquery-ui, materialize, leaflet. Все библиотеки будем подключать из удаленного хранилища:

html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/jquery.ui/1.11.4/jquery-ui.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/materialize/0.97.8/css/materialize.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/leaflet/1.0.2/leaflet.css">
<script src="https://cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.ui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdn.jsdelivr.net/materialize/0.97.8/js/materialize.min.js"></script>
<script src="https://cdn.jsdelivr.net/leaflet/1.0.2/leaflet.js"></script>
<title>video</title>
</head>
<body>
<iframe width="560" height="315" src="https://www.youtube.com/embed/CpAcxbtXUgQ" frameborder="0" allowfullscreen></iframe>
</body>
</html>

В этом случае результаты такие:

2.jpg

2,30s - не очень-то быстро, учитывая, что из контента на странице только одно видео.

А теперь представьте, что таких видео несколько… Я думаю, что эту проблему необходимо решить!

Пишем плагин

Разметка и стили

Идея плагина довольно простая - вместо видео показывать заранее заготовленную картинку или просто цветной блок, при клике на который будет уже подгружаться видео.

Html разметка для пллагина будет состоять из одного единственного блока:

html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.video {
display: block;
position: relative;
background-color: tomato;
margin: 0;
padding: 0;
cursor: pointer;
width: 560px;
height: 315px;
}
.video iframe {
display: block;
margin: 0;
padding: 0;
}
.video_load:after {
display: none !important;
}
</style>
<title>video</title>
</head>
<body>
<div class="video"></div>
</body>
</html>

Вся движуха будет разворачиваться как раз вокруг блока с классом video. Как видите, мы задали ему некоторорые базовые стили.

Класс video_load мы будем добавлять в момент загрузки видео, чтобы кнопка плей нам не мешалась.

Теперь нам необходимо сделать кнопку play, чтобы наш макет выглядел как настоящее видео уже загруженное с youtube:

play.png

base64
1
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEQAAAAwCAYAAACooNxlAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMzQDW3oAAASfSURBVGhD7ZvbTxxVHMfHS6IxGjX+C7418YUYzYa4M2e2sCRQKXStpQmQFEptlF6MMcE2pEWa+NDWvvRCfLBiazStDdmXjTS1hIX4IDTxVnjAkpp2g/AiC8Esu2f8/mZn0u32F9guZ1iG9Zt8dnbmd67fnTOXw0ErVJFI5KlQKPRiMBh8Vdf1N8ygGRZB8a5hGO3gEDgqdHECnAJnsf8FthfBJfAt9q8QwhC0jRaCkzabD2U4ZV3EPpV9FlBdJ7B/FFAb2qlN4i1RQ22ktoKXqO1ON4pTd3f3k0KIGrtSQwyjorvYLgHLp1DbqQ9xQzfOUd8KNgmOvolMv+QUtln5FT90wOk2LyTYhYSpvIybmWX0udnp/sPCmAtSgrwMmx6MhjSG0FbHhqzC4fAzCPzJZSgT7tbW1j7n2KFpuHjuYRKVF0K879hhXzsG2UTlhC5GbDNwV3kahiyyicqLFLx4VsOp8hoTVEq4Omx1ftApIzsikotvFEzTfJ2GSxMXVEVzc7M1MzNjkdLptHX1ylVZV1vHpi05QrSSIcfYoCJu/nhT2m7kaG5uzurp6ZGmMNk8pQJe9JIhX3JBVUxMTDg2PKqxsTHZ0tLC5isF8OJrDV+u5wdUspIhpOXlZau/v1/WhGvY/OsJnsVuaF6/t6xmiKvE/YTs6uoq7UVXF7/RGfLXIwGFFGqIq/hwXDbtamLL8hqcHPfoGvIPF1TF4xpCWlpasvr6+mR1VTVbpockacikmYAyijHE1fT0tDx86PC6DSN4kaEhwwZVsRZDSFJKa/CHQdnY0MiWr5oNb4irZDJpnfn8jAyZIbYeVfjGEFeTk5Ny/3v72bpU4DtDSJlMxhoYGJD1b9ezda4FXxrianZ2Vu5u2s3WWyy+NoR07ftrSu9CvjckGo3+b4irhYUFq21PG1tvsfjWkJGREU8e8X1nSCKRsI58csSzp1ffGJJKpazLly57Pk3gC0PGx8dla2srW75qyJBM/kGVrMUQmmrs7e1dt6lG++UOHwtcUBXFGEKT0fR8sa1uG1umhyTpDLmfd1Apj2vI7T9uy46ODrYsr8lOEOnG71xQFYUaMj8/b50+dbq0M/H2FKIuhtigIlYzhOY7YrGYbNjewOZfT3By3KApxG+4oCpWMmRqakoe6DxQ2onlHOw/Q+DjMy6oitHRUaf7D7S4uGidP3deVm2tYvOUCnjxKRnSzgVVsa9jn/3O4WpoaEjufGcnm7bUmLrZQoYEuKBKaCLn+LHjcm/73g0zPDjgRQUth3geFxNPZ979ADz4l1ZS2WtEcODn/ARlyLBtBgm33o+ZBOWFEAcdOzStsrLyZZwyc2zC8uDvQCDwgmNHVvaSaENs6IueR0j0fYdjw8Nyhk45mSJxZ/nI6T4vjKXtGD73mMybCruPQVHvdHtl0SJWemAD9B8Jd4CfF/67UB/uwIgofvS2ioqKBwt1i9ATpmm+AoO2mEFThxqpUAyxD3GM1qidxPcL4CvwHRjAsRi4ju/08hgHP+VwazVQ7ji2uXniTlm04ilm15Gti+q8gGMn7bagTdQ2aiO11W4z2k59yHZlJWnaf6SUF6UXQMDFAAAAAElFTkSuQmCC

play-hover.png

base64
1
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEQAAAAwCAYAAACooNxlAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMzQDW3oAAANaSURBVGhD7Zvba9NQHMfzX9jGJu0SvIAwBFGRKQwUJmyICiLik4Ii6IMwZciGIshkKF5eRYdDZNZpRXzYzfmgTdvNgdsQde7B2zZ3ERQVwafj7xsbV+vPTdamOVn8wYeT9fzO7cNOmpZT5W/RH9JNotbhcUg/aanRcz2Ly1q6IsbdTs3sadfMDDFAPE+Ho98oT3gBxsYcsnPJdGrGA8wRc02q0fOYO+X9WgthZpc5dyCZOqh7pMZG6JqdgN/B2rKSZheDBEp+ktt4IfNQjQ1SyUtBBckYz20QBGjN76n8XQpeIFvPchODBEkZpnJGSm9Yb8xPChp0Y26yZdAfZlKNTeUnBA16B/1IpQkheBtikwJIrdIb0k8xFYEkHdZPK/cjRpyrDCLdmnFHKcVb7XBdvfhwKyGmWm8Ka00FmyMD5GIS9xC2slhkqqrF97Fx4QSuRxpOsLky4LqQoWMNWRUzASn4j+nfsYtt4yWeCHECYiZb48IqX8W29QJPhTgBMS+O1LHtS40UQhDONuqt3sr2UyqkEeIExIy3XBPW8nK2P7eRTogTEPP00GG2TzeRVgjC3kZtCZHeWMX27QZSC3ECYt5dbhbpsmXsGMXEF0KcgJjBvfvZcYqFr4QgIGU63iZS6zaw4xWK74Q4ATEv64+zYxaCb4UgIMVau54dd774XkiqopIdd774esu8bmxixywEX95U7Uf8mm3seIXiKyGQ4faHQF8IgYiJ6zeEtXI1O0YxkVqIsz36d+5m+3YDaYVAhhdfNUonBCLsL6OL/Hzxr0glBDIG9uxj+ykVUgiBiLeXrtCn2aVsH6XEUyH2TbMtIVKVm9i2XuCZEMgYOnCQbeMlrgvp27LdXrwTuB5tvipSS1aw+V6jJNXoNFdRTPCZA88TILO5hs2RgaQam1C6NOMeVxlEuiPGbcUKR89wlUEEJ6lwD/l/YGaGWggxU+Ho17yKwEE75ROVPw/e0Y31Qn5C0CAhZ20ZCHoBZ1RH85OCAq39DZV/nlUN4tah/4wvVM56mhm22MYLDVrrKyp5GU4gAYdYS/HA5hU4l5sK6U10PbuM3EAyYf+com+RdpRsXuyJlLXSg1xHh2ZY7bo5QFvsMwaQCcwJc8McMVfMGXPHGqh+jp+HKMoPg5XHKtJNDT8AAAAASUVORK5CYII=

Закодировать свои картинки в Base64 можно [тут]

Сейчас нам нужно разместить кнопку внутри блока, для этого допишем ему вот такие стили:

css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.video:after {
content: '';
display: block;
position: absolute;
background-image: url('копируем сюда Base64 код первой картинки');
background-position: center center;
background-repeat: no-repeat;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.video:hover:after {
background-image: url('копируем сюда Base64 код второй картинки');
}

Простой Javascript

Самое простое, это конечно воспользоваться библиотекой jquery или zepto, но сейчас появилась тенденция отказываться от этих библиотек. Поэтому будет представлено два варианта кода:

  • Jquery
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function videoLoader(block, video) {
block.click(function() {
if (block.hasClass('video_load')) {
return false;
}
block.html(video);
block.addClass('video_load');
});
}
videoLoader(
$('.video'),
'<iframe width="100%" height="100%" src="https://www.youtube.com/embed/CpAcxbtXUgQ?autoplay=1" frameborder="0" allowfullscreen></iframe>'
);
  • Vanilla js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function videoLoader(block, video) {
block.addEventListener('click', function() {
if (block.classList.contains('video_load')) {
return false;
}
block.innerHTML = video;
block.classList.add('video_load');
});
}
videoLoader(
document.querySelector('.video'),
'<iframe width="100%" height="100%" src="https://www.youtube.com/embed/CpAcxbtXUgQ?autoplay=1" frameborder="0" allowfullscreen></iframe>'
);

Как видите, это не очень сложная функция. Главное правильно подготовить код загружаемого видео. Нужно указать высоту и ширину в 100%, а так же указать, чтобы видео воспроизводилось автоматически - autoplay=1.

Вообще в документации и документации есть много параметров, которыми можно настраивать видео как нам нужно.

Jquery плагин и ES6 класс для YouTube и Vimeo

Плюс функции выше в том, что в неё можно вставлять видео с абсолютно любого видеохостинга. Но в то же время ей нужно передавать длинную строку с кодом видео, да и параметры нужно каждый раз прописывать. Мне кажется это не слишком удачным решением. Поэтому мы напишем плагина для YouTube и Vimeo. Для остальных видеохостингов Вы сможете написать плагины по аналогии.

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(function($) {
jQuery.fn.videoLoader = function(param) {
param = $.extend({
type: 'youtube', // тип, youtube или vimeo
id: false, // id видео
// Для Youtube
control: true, // Показывать/скрывать элементы управления видео
rel: true, // Показывать/скрывать показ похожих видео, после окончания ролика
info: true, // Показывать/скрывать информацию о ролике
logo: true, // Показывать/скрывать логотип youtube на элементах управления
// Для Vimeo
loop: false // Проигрывать ли видео по кругу
}, param);
if (param.id === false) {
alert('Введите ID видео');
}
var make = function() {
var $this = $(this),
url = '';
param.control = param.control ? 2 : 0;
param.rel = param.rel ? 1 : 0;
param.info = param.info ? 1 : 0;
param.logo = param.logo ? 0 : 1;
param.loop = param.loop ? 1: 0;
$this.on('click', function(e) {
var iframe, url;
if ($this.hasClass('video_load')) {
return false;
}
$this.addClass('video_load');
switch (param.type) {
case 'vimeo':
url = 'https://player.vimeo.com/video/'+ param.id + '?autoplay=1&loop=' + param.loop;
break;
default:
url = 'https://www.youtube.com/embed/'+ param.id + '?autoplay=1&autohide=1&rel=' + param.rel + '&showinfo=' + param.info + '&modestbranding=' + param.logo + '&controls=' + param.control;
}
iframe = $('<iframe/>', {
'frameborder': '0',
'src': url,
'width': '100%',
'height': '100%',
'webkitallowfullscreen': '',
'mozallowfullscreen': '',
'allowfullscreen': ''
});
$this.append(iframe);
});
};
return this.each(make);
};
})(jQuery);
// Вызов
$('.video').eq(1).videoLoader({
type: 'vimeo',
id: '197047485'
});

В принципе все параметры прописаны в коде. Небольшое уточнение для ютуба:

При скрытии информации о ролике, в правом нижнем углу появляется логотип-ссылка YouTube. И этот логотип уже не убирается настройкой показа/скрытия логотипа

И для разнообразия, давайте напишем этот же плагин в ООП стиле на ES2015:

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class VideoLoader {
constructor(container, // Блок в который будем загружать видео
{
id = false, // id видео
type = 'youtube', // тип, youtube или vimeo
// Для Youtube
control = true, // Показывать/скрывать элементы управления видео
rel = true, // Показывать/скрывать показ похожих видео, после окончания ролика
info = true, // Показывать/скрывать информацию о ролике
logo = true, // Показывать/скрывать логотип youtube на элементах управления
// Для Vimeo
loop = false // Проигрывать ли видео по кругу
}) {
this.cont = document.querySelector(container);
this.id = id;
this.type = type;
this.rel = rel ? 1 : 0;
this.info = info ? 1 : 0;
this.logo = logo ? 0 : 1;
this.loop = loop ? 1 : 0;
if (this.id === false) {
alert('Введите ID видео!');
}
}
init() {
let iframe, url;
this.cont.addEventListener('click', ()=> {
if (this.cont.classList.contains('video_load')) {
return false;
}
this.cont.classList.add('video_load');
switch (this.type) {
case 'vimeo':
url = `https://player.vimeo.com/video/${this.id}?autoplay=1&loop=${this.loop}`;
break;
default:
url = `https://www.youtube.com/embed/${this.id}?autoplay=1&autohide=1&rel=${this.rel}&showinfo=${this.info}&modestbranding=${this.logo}&controls=${this.control}`;
}
iframe = `
<iframe
src="${url}"
frameborder="0"
width="100%"
height="100%"
webkitallowfullscreen
mozallowfullscreen
allowfullscreen
></iframe>
`;
this.cont.innerHTML = iframe;
});
}
}
// Вызов
new VideoLoader('.video', {
id: '197047485',
type: 'vimeo'
}).init();

Как видите, с новым стандартом код получился практически такой же по размеру как и плагин.


Если Вы еще не знакомы с ES2015, то советую пройти бесплатный курс по новому стандарту от CodeDojo. Автор рассказывает материал очень доступно и легко объясняет сложные вещи. Рекомендую!


Теперь, давайте посмотрим на время загрузки страницы с подключенными библиотеками:

3.jpg

667ms - очень даже неплохо!

Демо примеры

Jquery плагин:

See the Pen videoLoader-jquery by Alexandr (@login2030) on CodePen.

OOP ES2015:

See the Pen videoLoader-ES2015 by Alexandr (@login2030) on CodePen.

Заключение

В этой статье мы рассмотрели способ ускорения загрузки страницы в которую встроено видео. Теперь Вы сможете поставить любую картинку на превью к видео, а так же подстраивать кнопку воспроизведения под дизайн Вашего сайта.