Зараз обговорюють

"Тобто є ряд завдань, які взагалі без рекурсії не наважуються."  - це як розуміти? Перефразуй, будь ласка. 

виправив, йшлося про те що деякі завдання можна вирішити лише при використанні рекурсії

Спасибі дуже корисна стаття

А ще щось планується подібного найближчим часом?


Дякую за підтримку, радий що Вам сподобалось!

Так маю вже майже дороблений проект по управлінні Audio файлом, на заміну стандартним клавішам управління HTML5, але ще не встиг відтестувати програвання файлів з інтернету, поки лише локально працює

Надіюсь найближчим часом дороблю й закину

Рахунки

webmoneyeur - E385818210641
usd - Z304643423050
uah - U354026817492
rub - R301704373231easypay80002677bitcoin1F5HRGroUtEQW9HBNbeew8iKh5KQ8vJxzw

Зворотній зв'язок

Для покращення роботи сайту надсилайте свої зауваження:
mailЗауваження
mailПропозиція

Статистика

UkrNET - поисково-информационный ресурс

JavaScript : Створення модуля управління для HTML5 Video Player

Дещо перебудувавши код із попередньої теми про створення Audio Player створимо управління для відео файлу, використовуючи тег Video із HTML5

Примітка: працюватимемо із форматом mp4.

Додатково для роботи ми також буде використовувати наступні бібліотеки:

- jQuery - v3.1.1 jquery.com

- jQuery UI - v1.10.4 jqueryui.com

Примітка: jQuery UI - містить різні готові надбудови користувацького інтерфейсу (Menu, Progressbar, Selectmenu, Slider, Tabs, Tooltip та інші). Нам знадобиться лише Slider

Для кнопок використаємо прості символи, дизайн кожен може зробити собі в залежності від своїх потреб, а поки перейдемо до самого написання коду.


HTML - код

Усі потрібні компоненти будемо наповняти в наступний блок

<div id="myVideo">
	<div id="CurVideo"></div> //блок де буде містити поточне відео, та кнопки управління
	<div id="VideoPlayList"></div> //блок із списком відео-файлів для відтворення
</div>

CurVideo

В даному блоці розмістимо сам плеєр та його додаткові елементи (які самі зробимо):

Додаємо сам тег video, в який будемо відтворювати потрібний запис формату mp4

<video id="VideoPlayer" preload="auto">
	<source id='sourceVideo' src="" type='video/mp4;'>
</video>

також додамо ще два блоки:

- опис відео, буде містити назву відтворюваного файлу (назва зазначена в плейлисті)

<div id="videoDescription"></div>

- кнопки управління відео плеєром будуть в наступному блоці:

<div id="videoPlayerControls">
	[controls]
</div>

Play/Pause

<div id="VideoPlay" class="VideoPlayerButton" title="Відтворити">►</div>

Time - інформація про поточний та загальний час файлу

<div  class="VideoPlayerTime"> <span id="CurTime" title="Поточний час">00:00</span><span> / </span><span id="MaxTime" title="Тривалість відео">00:00</span></div>

Previous - перемикання на попередній елемент списку відтворення

<div id="PreviousVideoFile" class="VideoPlayerButton" title="Попередній файл">◄</div>

ProgressBar - прогрес відтворення

<div class="VideoProgressBar" title="00:00"></div>

Next - перемикання на наступний елемент списку відтворення

<div id="NextVideoFile" class="VideoPlayerButton" title="Наступний файл">►</div>

Блок управління звуком

<div id="VideoVolumControl">
	<div id="VideoVolumeMute" title="Викл. звук">♫ 100%</div>
	<div class="VideoVolumeSlider" title="100%"></div>
</div>

Downloal - для можливості завантаження відео

<div id="DownloalVideoFile" class="VideoPlayerButton" title="Завантажити файл">▼</div>

Блок управління швидкістю відтворення відео файлу

<div id="VideoPlaySpeed" class="VideoPlayerButton" title="Швидкість відтворення">
	<ul id="VideoPlaySpeedMenu">
		<li>2.0x</li>
		<li>1.5x</li>
		<li>1.0x</li>
		<li>0.5x</li>
	</ul>
	<span>1.0x</span>
</div>

FullScreen - для розгортання на весь екран

<div id="VideoFullScreen" class="VideoPlayerButton" title="На повний екран">∎</div>

VideoPlayList

Список відтворення буде простий нумерований:

<ol>
	<li data-src="[url1]"><span></span>[audio name 1]</li>
	<li data-src="[url2]"><span></span>[audio name 2]</li>
	<li data-src="[url3]"><span></span>[audio name 3]</li>
</ol>

Пустий тег span буде зазначати яке відео відтворюється, чи помилку завантаження (х)


JS - код

Для початку нам потрібно буде створити змінні які будуть відповідати за кожен елемент управління:

var playList = [] //масив url треків із нашого плейлисту
var playListNames = []
var videoElm; //наш HTML5 плеєр
//присвоюємо усі потрібні в подальшому блоки із кнопками управління
var videoDescription = "#videoDescription";
var VideoBlock = "#CurVideo";
var playerViewElm = "#videoPlayerControls";
var sourceElm = "#sourceVideo";
var playElm = "#VideoPlay";
var previousElm = "#PreviousVideoFile";
var nextElm = "#NextVideoFile";
var volumeElm = ".VideoVolumeSlider";
var muteElm = "#VideoVolumeMute";
var volumControlsElm = "#VideoVolumControl";
var progresElm = ".VideoProgressBar";
var curTimeElm = "#CurTime";
var maxTimeElm = "#MaxTime";
var playListElm = "#VideoPlayList";
var palySpeedElm = "#VideoPlaySpeed";
var palySpeedMenuElm = "#VideoPlaySpeedMenu";
var downloadElm = "#DownloalVideoFile";
var videoFullScreenElm = "#VideoFullScreen";
var curFile = null; //№ поточного запису
var curProgress = 0; //секунда на якій перебуває відтворення
var mouseIsHoldProgress = false //булева змінна знадобиться при внесені змін користувачем в progresElm;

Основний наш код розмістимо в наступній функції:

$(document).ready(function () {
	try{
		[управління плеєра]
	}
	catch (e){
		alert(e);
	}
});

Функція буде спрацьовувати після завантаження структури сторінки з якою ми вже зможемо працювати, а блоки try/catch будуть перехоплювати несподівані помилки при роботи коду, якщо такі виникатимуть.

Тобто блок try намагатиметься виконати все йому задане, а якщо в він не зможе щось обробити та викличе помилку то її перехопить catch та виведе повідомлення із помилкою.

Управління плеєра

Зазначаємо що плеєр зараз не в повноекранному режимі

var isFullscreen = false;

Присвоюємо наш тег плеєра

videoElm = document.getElementById("VideoPlayer");

Наповнюємо масиви даними з плейлиста:

$(playListElm).find('li').each(function(){
	playList.push($(this).attr('data-src'));
	playListNames.push($(this)[0].innerText);
});

find - знаходить усі дочірні елементи в блоці зі списком, а each - забезпечує виконання функції для кожного знайдено елементу


При натисканні на елемент плейлисту нам потрібно буде відтворювати трек на який натиснули, тож:

$(playListElm).on("click", "li", function(){
	for(var i = 0; i < playList.length; i++){
		if($(this).attr('data-src') == playList[i]){				
			changeFile(i);
			break;
		}
	}
});

Обробка кнопки Play/Pause. Відповідно запускає, або зупиняє відтворення

$(playElm).on("click", function(){
	if($(sourceElm).attr('src').length > 0)
		(videoElm.paused == true) ? videoElm.play() : videoElm.pause();	
	else
		changeFile(0);
});

Кнопки переключення треку:

//Попередній файл
$(previousElm).on("click", function(){
	changeFile(checkNeedFile(0));
});
//Наступний файл
$(nextElm).on("click", function(){
	changeFile(checkNeedFile(1));
});

checkNeedFile() перевіряє елемент на який ми хочемо змінити. 0 - попередній, 1 - наступний (розглянемо детальніше дану функцію пізніше)


Вкл/Викл звуку

$(muteElm).on("click", function(){
	(videoElm.muted == true) ? videoElm.muted = false : videoElm.muted = true;
	(videoElm.muted == true) ? $(muteElm)[0].innerHTML = "♫x " + Math.floor(+videoElm.volume * 100) + "%" : $(muteElm)[0].innerHTML = "♫ " + Math.floor(+videoElm.volume * 100) + "%";
	(videoElm.muted == true) ? $(muteElm).attr('title', 'Вкл. звук') : $(muteElm).attr('title', 'Викл. звук');
});

Швидкість відтворення відео

$(palySpeedElm).on("mouseenter", function (){
	$(palySpeedMenuElm).css("display", "block");
});
$(palySpeedElm).on("mouseleave", function (){
	$(palySpeedMenuElm).css("display", "none");
});
$(palySpeedMenuElm).find('li').each(function(){
	$(this).on("click" ,function(){
		videoElm.playbackRate = +$(this)[0].innerHTML.replace("x","");
	})
});
>

та подія яка буде реагувати на зміну швидкості відтворення

videoElm.onratechange = function(){			
	$(palySpeedElm + " span")[0].innerHTML = videoElm.playbackRate.toFixed(1) + "x";
};

Обробка помилок при роботі з файлом джерелом

$(sourceElm).on("error", function (){
	checkPlaylist(1);
});
videoElm.onerror = function(){
	checkPlaylist(1);
};

checkPlaylist() відповідає за відображеня відтворення, чи помилок в плейлисті. 0 - відтворюється, 1 - помилка (розглянемо детальніше дану функцію пізніше)


Якщо файл можна відтворити тоді запускаємо його на відтворення:

videoElm.oncanplay = function(){
	$(progresElm).slider("option", "value", 0);
	videoElm.play();
	$(palySpeedElm + " span")[0].innerHTML = videoElm.playbackRate.toFixed(1) + "x";
	checkPlaylist(0);
};

Подія початку відтворення та встановлення паузи для треку буде змінювати символ елемента на потрібний

videoElm.onplay  = function(){
	$(playElm)[0].innerHTML = "❚❚";
	$(playElm).attr('title', 'Пауза');
};

videoElm.onpause  = function(){
	$(playElm)[0].innerHTML = "►";
	$(playElm).attr('title', 'Відтворити');
};

Подія що реагує на завершення відтворення файлу, та перемикає на наступний при можливості

videoElm.onended = function(){
	changeFile(checkNeedFile(1));
};

Подія що реагує на початок процесу завантаження файлу та здійснює відображення в плейлисті

videoElm.loadstart = function(){		
	checkPlaylist(0);				
};

подія що реагує на зміну тривалості запису (в нашому випадку це зміна файлу відтворення) та занулює поточний час

videoElm.durationchange = function(){
	$(curTimeElm)[0].innerHTML = "00:00";
};

Подія що реагує на завантаження даних про файл та встановлює час треку maxTimeElm і змінює максимальне значення нашого слайдера progresElm

videoElm.onloadedmetadata = function(){
	$(maxTimeElm)[0].innerHTML = converToTime(this.duration);
	$(progresElm).slider("option", "max", +videoElm.duration);		
};

converToTime() відповідає за конвертування секунд у часовий проміжок (розглянемо детальніше дану функцію пізніше)


Подія що реагує на зміну секунди відтворення та змінює позицію слайдера до поточного місця відтворення, якщо не натиснута клавіша миші на елементі

videoElm.ontimeupdate = function(){
	$(curTimeElm)[0].innerHTML = converToTime(videoElm.currentTime);
	if(mouseIsHoldProgress == false)
		$(progresElm).slider("option", "value", +videoElm.currentTime);
};

Регулятор гучності (UI елемент із бібліотеки)

$(volumeElm).slider({
	orientation: "vertical",
	animate: true,
	range: "min",
	value: 1,
	min: 0,
	max: 1,
	step: 0.01,
	slide: function(event, ui){
		videoElm.volume = ui.value // при зміні слайдера встановлює відповідний рівень звуку 
	}			
});

та подія що реагує на зміну гучності (змінює слайдер до поточного рівня звуку)

videoElm.onvolumechange = function(){
	var volumRate = Math.floor(+videoElm.volume * 100);
	$(volumeElm).slider("option", "value", +videoElm.volume);
	$(volumeElm).attr('title', volumRate + '%');
	if(videoElm.volume>0)
		$(muteElm)[0].innerHTML = "♫ " + volumRate + "%";
	else
		$(muteElm)[0].innerHTML = "♫x " + volumRate + "%";
};

Відображення/приховування блоку із регулятором гучності при наведені

$(volumControlsElm).on("mouseenter", function (){
	$(volumeElm).css("display", "inline-block");
});
$(volumeElm).on("mouseleave", function (){
	$(volumeElm).css("display", "none");
});

Процес відтворення треку (UI елемент із бібліотеки)

$(progresElm).slider({
	orientation: "horizontal",
	animate: true,
	range: "min",
	value: 0,
	min: 0,
	max: 120,
	step: 1,
	stop: function(event, ui){
		if($(sourceElm).attr('src'))
			videoElm.currentTime = ui.value; // при зміні слайдера перемотує трек до потрібного місця
	}
});

Перевірка натиску клавіші миші на progresElm

$(progresElm).mousedown(function(){
	mouseIsHoldProgress = true;
});
$(document).mouseup(function(){
	if(mouseIsHoldProgress == true)
		mouseIsHoldProgress = false;
});

Зміна атрибуту title для відображення часу на який перемотаємо час відтворення

$(progresElm).mousemove(function(e){
	var x = e.pageX - $(progresElm).offset().left;
	$(progresElm).attr('title', converToTime(videoElm.duration * (x / $(progresElm).width())));
});

Завантаження поточного треку

$(downloadElm).on("click", function(){
	var link = document.createElement('a'); // створюємо пустий тег a
	link.setAttribute('href',playList[curFile]); // додаємо йому посилання на трек
	link.setAttribute('download','download'); // задаємо атрибут download
	onload=link.click(); // завантажити елемент
});

Приховуємо контроли та назву відео яке відтворюється якщо користувач не рухає мишкою по блоку з відео

$(playerViewElm).css("display", "none");
$(videoDescription).css("display", "none");
var showDiv = function(){
	$(VideoBlock).css("cursor", "none");
	$(playerViewElm).css("display", "none");
	$(videoDescription).css("display", "none");
	$(palySpeedMenuElm).css("display", "none");
};
var timeOut = setTimeout(showDiv, 2000);
$(VideoBlock).on("mousemove", function (){
	clearTimeout(timeOut);
	$(VideoBlock).css("cursor", "default");
	$(playerViewElm).css("display", "block");
	$(videoDescription).css("display", "block");
	timeOut = setTimeout(showDiv, 2000);
});		
videoElm.onclick = function(){
	if($(sourceElm).attr('src').length > 0)
		(videoElm.paused == true) ? videoElm.play() : videoElm.pause();	
	else
		changeFile(0);
}

Управління повноекранним режимом відтворення згорнути/розгорнути

$(videoFullScreenElm).on("click", function(){
	if(!isFullscreen){
		if (videoElm.requestFullscreen)
			videoElm.requestFullscreen();
		else if (videoElm.msRequestFullScreen)
			videoElm.msRequestFullScreen(); // IE >= 11
		else if (videoElm.mozRequestFullScreen)
			videoElm.mozRequestFullScreen(); // Firefox
		else if (videoElm.webkitRequestFullscreen) 
			videoElm.webkitRequestFullscreen(); // Chrome - Safari
		isFullscreen=true;
	}
	else{
		if(document.cancelFullScreen) 
			document.cancelFullScreen();
		else if(document.msCancelFullScreen)
			document.msCancelFullScreen();
		else if(document.mozCancelFullScreen)
			document.mozCancelFullScreen();
		else if(document.webkitCancelFullScreen)
			document.webkitCancelFullScreen();
		isFullscreen=false;	
	}
});

Додаткові функції

Дані функції не включаються у блок [управління плеєра] та розміщаються поза межами функції $(document).ready

Визначаємо потрібний елемент масиву, та перевіряємо чи можна на нього перемкнути:

function checkNeedFile(param){
	var needFile;
	if(param == 0){ // перевіряємо чи можна перемкнути на потрібний елемент
		if(curFile > 0)
			needFile = curFile - 1;
		else
			needFile = -1;		
	} else{
		if(curFile < (playList.length-1))
			needFile = curFile + 1;
		else
			needFile = -1;
	}
	return needFile; // повертаємо потрібний № елемента масиву
};

param - приймає значення 0 (на попередній), або 1 (на наступний)


Зміна поточного файлу

function changeFile(newFile){
	if(newFile >= 0){
		curFile = newFile; // зберігаємо в глобальній змінній значення поточного запису
		if(videoElm.canPlayType('audio/mp4;"') != ""){ // якщо браузер може відтворити відповідний тип тоді:
			videoElm.pause();
			$(sourceElm).attr('src', '');
			videoElm.load();
			$(sourceElm).attr('src', playList[curFile]);
			videoElm.load();
		} else{
			checkPlaylist(1);
		}
		$(videoDescription)[0].innerHTML = playListNames[curFile];
	}
};

Позначки в плейлісті по поточному треку (відтворюється, чи сталась помилка). Приймає аргумент param: 0 - якщо відтворюється, 1 - якщо помилка

function checkPlaylist(param){
	var symbol;
	var i = 0;
	(param == 0) ? symbol = "♫ " : symbol = "x "
	$(playListElm).find('li').each(function(){ // перебираємо плейлист для відображення його стану
		if(i == curFile){
			$(this).find("span")[0].innerHTML = symbol;
			$(this).css('color', 'black');
		}
		else{
			$(this).find("span")[0].innerHTML="";
			$(this).css('color', '#ccc');
		}
		i++;
	});
};

Управління плеєром з клавіатури

$(document).keydown(function(e){
	var unicode = e.charCode ? e.charCode : e.keyCode; // зберігаємо натиснуту клавішу
	if (unicode == 34) //Page Down - попередній файл
		changeFile(checkNeedFile(0));
	else if (unicode == 33) //Page UP - наступний файл
		changeFile(checkNeedFile(1));		
	else if (unicode == 37) //Ліва стрілка - перемотати назад на 5 сек
		if(videoElm.currentTime >= 5)
			videoElm.currentTime -= 5;
		else
			videoElm.currentTime =0;
	else if (unicode == 39) // Права стрілка - перемотати вперед на 5 сек		
		if(videoElm.currentTime <= videoElm.duration)
			videoElm.currentTime +=5;
		else
			videoElm.currentTime = videoElm.duration;
	else if (unicode == 32) //Пробіл - Play/Pause
		playPause();
	else if (unicode == 38) { //Стрілка вгору - збільшити гучність + 5
		if(Math.floor(videoElm.volume * 100) <= 95)
			videoElm.volume = (Math.floor(videoElm.volume * 100) + 5) / 100;
		else if(Math.floor(videoElm.volume * 100) > 95)
			videoElm.volume = 1;
	} else if (unicode == 40) { //Стрілка вниз - зменшити гучність - 5
		if(Math.floor(videoElm.volume * 100) >= 5)
			videoElm.volume = (Math.floor(videoElm.volume * 100) - 5) / 100;
		else if(Math.floor(videoElm.volume * 100) < 5)
			videoElm.volume = 0;
	}
});

Перетворення секунд в час для відображення значень поточного відтворення та тривалості треку в часовому форматі. Приймає аргумент seconds - секунди

function converToTime(seconds){
	var h, m, s;
	h   = Math.floor(seconds / 3600);
    m = Math.floor((seconds - (h * 3600)) / 60);
    s = Math.floor(seconds - (h * 3600) - (m * 60));
	// повертаємо рядок потрібного формату
	if(h > 0)
		return (h < 10 ? "0":"") + h + ":" + (m < 10 ? "0":"") + m + ":" + (s < 10 ? "0":"") + s;
	else
		return (m < 10 ? "0":"") + m + ":" + (s < 10 ? "0":"") + s;	
};

Приклад реалізованого плеєра

В кінці після зібрання всього коду ми отримаємо наступний плеєр:

Примітка: усі використані CSS стилі та JS код можна завантажити за посиланнями наведеними в розділі "Файли для завантаження"

00:00 / 00:00
♫ 100%
  • 2.0x
  • 1.5x
  • 1.0x
  • 0.5x
1.0x
  1. Ocean

Файли для завантаження

Завантажити з Завантажити з


view395like0dislike0 avatard_l4w clock 2017-04-25 09:29

Коментарі:



Для даної статті відсутні коментарі

Про нас

"Programmers World" розроблено з метою полегшення в освоєнні навичок програмування, та поширення матеріалів з сфери ІТ Українською мовою.

Кожен бажаючий може безкоштовно користуватися ресурсами сайту, щоб:

- Вивчати теоретичні аспекти мов програмування

- Переглядати практичне застосування теорії при виконанні різних міні проектів з відкритим кодом

- Розміщати свої завдання на форумі для допомоги в їх реалізації, або готового коду який може бути корисний іншим користувачам

- Спілкуватись з іншими користувачами та обмінюватись досвідом

Сайт функціонує на безопланій основі та ентузіазмі розробника, якщо Ви бажаєте долучитись до розвитку даного проекту то можете пожертвувати кошти на рахунки розміщені в блоці "Допомога сайту".

Сайт

Зареєстровані користувачі можуть скористатися системою діалогів, в профілі користувача, для отримання потрібної інформації. Написати!

Також Ви можете використати форми відправки Зауважень та Пропозицій.


Електронна пошта

Ви можете звертатись на нашу поштову скриньку site.programmersworld@gmail.com

www.000webhost.com