ساخت ویدیو پلیر حرفه ای با جاوا اسکریپت ( لیست پخش ، پیش نمایش فریم )

ویدیو پلیر با جاوا اسکریپت – در این آموزش با javascript خالص بدون هیچ فریمورک و کتابخانه ای ویدیو پلیر حرفه ای و شخصی سازی شده ی خودمان را می سازیم .
ویدیو پلیر اختصاصی با امکان playlist و پیش نمایش هر فریم ثانیه را در زمان بردن ماوس بر روی seekbar را دارد .
برای درک بهتر ویدیوی معرفی را تماشا نمایید :
ویدیوی معرفی پلیر اختصاصی با js
فایل index.html
<!DOCTYPE html> <html lang="fa" id="xhtml"> <head> <meta charset="UTF-8"> <title>Rapidcode.iR - سورس کد</title> <link rel="stylesheet" href="static/css/main.css"> </head> <body> <div class="container"> <a id="introduce" href="https://rapidcode.ir" target="_blank">رپید کد • کتابخانه مجازی برنامه نویسان</a> <div class="video-wrapper"> <div id="preview-thumbnail"> <img src="static/video/thumbnails/Lamborghini Urus (1).png"> </div> <ul id="video-playlist"> <li data-src="static/video/Lamborghini Urus.mp4">لامبورگینی اوروس</li> <li data-src="static/video/FORD Mustang GT.mp4">فورد موستانگ نیو</li> </ul> <div class="video-player-wrapper"> <video id="my-custom-video-play" src="static/video/Lamborghini Urus.mp4"></video> <div class="video-controls"> <span class="icon-player play-pause"></span> <div data-preview="true" id="timer" class="seekbar timer"> <div data-preview="true" id="loaded"></div> <div data-preview="true" id="progress"><div data-preview="true" id="handler"></div></div> <span id="remain">-00:00</span> </div> <span class="icon-player sound-mute"></span> <div class="seekbar sound"> <div id="loaded"></div> <div id="progress"><div id="handler"></div></div> </div> <span class="icon-player full-screen"></span> </div> </div> </div> </div> <script src="static/js/app.js"></script> </body> </html>
اسکریپت app.js جهت کنترل بر رویداد ها و کنترل پلیر
// DOM const videoDOM = document.getElementById('my-custom-video-play'); const seekbarDOM = document.getElementsByClassName('seekbar'); const seekbarTimersDOM = document.querySelector('.seekbar.timer'); const seekbarVolumeDOM = document.querySelector('.seekbar.sound'); const playpauseDOM = document.getElementsByClassName('play-pause')[0]; const soundmuteDOM = document.getElementsByClassName('sound-mute')[0]; const remainDOM = document.getElementById('remain'); const fullScreenDOM = document.getElementsByClassName('full-screen')[0]; const previewThumbnailDOM = document.getElementById('preview-thumbnail'); const videoPlaylistDOM = document.querySelectorAll('#video-playlist li'); // Property const isMuted = videoDOM.hasAttribute("muted"); const isAutoplay = videoDOM.hasAttribute("autoplay"); var videoInterval; // init setInitialVideoOptions(); // set handlers Array.from(seekbarDOM).forEach((element) => { element.addEventListener("click", seekbarDOMHandlerClicked); element.addEventListener("mousemove", seekbarDOMHandlerClicked); element.addEventListener("mousemove", seekbarDOMHandlerShowThumbnail); }); Array.from(videoPlaylistDOM).forEach((element) => { element.addEventListener("click", videoPlaylistDOMHandlerClicked); }); videoInterval = setInterval(VideoOnUpdateTime, 100) playpauseDOM.addEventListener('click', playpauseDOMHandlerClicked); fullScreenDOM.addEventListener('click', fullScreenDOMHandlerClicked); window.addEventListener("dblclick", windowHandlerExitFullScreen); window.addEventListener("keyup", windowHandlerShortcut); window.addEventListener("mousemove", seekbarDOMHandlerShowThumbnail); // handlers function seekbarDOMHandlerClicked(event) { if (event.type != 'click' && event.buttons == 0) return false; const thisElement = this; const isSoundSeekbar = thisElement.classList.contains("sound"); const isTimerSeekbar = thisElement.classList.contains("timer"); if (isMuted && isSoundSeekbar) return false; const progressElement = thisElement.querySelector("#progress"); const finallWidth = moveRangeSlider(thisElement , event) if (finallWidth < 0 || 100 < finallWidth) return; progressElement.style.width = finallWidth + "%"; if (isTimerSeekbar) { videoDOM.currentTime = getNumberByPercent(finallWidth, videoDOM.duration); videoDOM.play() } else if (isSoundSeekbar) { if (thisElement.querySelector('#progress').clientWidth == 0) soundmuteDOM.classList.add("mute") else soundmuteDOM.classList.remove("mute") videoDOM.volume = finallWidth / 100; } } function videoPlaylistDOMHandlerClicked(){ const thisElement = this; clearInterval(videoInterval); videoDOM.pause(); const videoSrc = thisElement.dataset.src; videoDOM.src = videoSrc; videoDOM.load(); videoDOM.onloadeddata = function(){ setInitialVideoOptions(); videoInterval = setInterval(VideoOnUpdateTime, 100) videoDOM.play() } makePlaylistElementActive(videoPlaylistDOM); } function seekbarDOMHandlerShowThumbnail(event){ if(typeof event.target.hasAttribute == "undefined") return false; var videoFrame = getNumberByPercent(Math.round(moveRangeSlider(seekbarTimersDOM , event)), videoDOM.duration) if(!event.target.hasAttribute('data-preview') || (videoFrame < 0 || 100 < videoFrame)){ previewThumbnailDOM.style.display = "none"; return false; } videoFrame = Math.round(Math.abs(videoFrame)) == 0 ? 1 : Math.round(Math.abs(videoFrame)); var videoName = videoDOM.getAttribute('src'); videoName = videoName.substring(videoName.lastIndexOf('/')); videoName = videoName.replace(/\/|\.mp4/gi , ""); const frameFileTemplate = `static/video/thumbnails/${videoName} (${videoFrame}).png`; previewThumbnailDOM.querySelector('img').src = frameFileTemplate; const previewThumbnailXY = { x : previewThumbnailDOM.clientWidth, y : previewThumbnailDOM.clientHeight, } previewThumbnailDOM.style.left = event.screenX - previewThumbnailXY.x - 60 + "px"; previewThumbnailDOM.style.top = event.screenY - previewThumbnailXY.y - 200 + "px"; previewThumbnailDOM.style.display = "block"; } function videoDOMHandlerProgress() { const videoBufferedLastTimeRange = (videoDOM.buffered.length - 1); if (videoBufferedLastTimeRange < 0) return 0; const timeBuffered = videoDOM.buffered.end(videoBufferedLastTimeRange); return timeBuffered; } function VideoOnUpdateTime() { updateVideoPausePlayState(); const bufferedTimeAll = videoDOM.duration; const bufferedTime = videoDOMHandlerProgress(); seekbarTimersDOM.querySelector('#loaded').style.width = getPercentByNumber(bufferedTime, bufferedTimeAll) + "%"; seekbarTimersDOM.querySelector('#progress').style.width = getPercentByNumber(videoDOM.currentTime, bufferedTimeAll) + "%"; remainDOM.textContent = `- ${toMinutes(Math.round(videoDOM.duration - videoDOM.currentTime))}`; } function playpauseDOMHandlerClicked() { const thisElement = playpauseDOM; if (thisElement.classList.contains("pause")) { thisElement.classList.remove("pause"); videoDOM.pause(); } else { thisElement.classList.add("pause"); videoDOM.play(); } } function fullScreenDOMHandlerClicked() { if (videoDOM.requestFullscreen) videoDOM.requestFullscreen(); } function windowHandlerExitFullScreen() { if (screen.height == window.innerHeight) if (document.exitFullscreen) { document.exitFullscreen(); } } function windowHandlerShortcut(event){ if(event.code == "Space"){ playpauseDOMHandlerClicked(); } if(event.code == "KeyF"){ fullScreenDOMHandlerClicked(); } } // helpers function getPercentByNumber(piece, total) { const percent = piece / total * 100; return percent; } function getNumberByPercent(percent, total) { const number = percent * total / 100; return number; } function setInitialVideoOptions() { videoDOM.currentTime = 0; if (isAutoplay && isMuted) { playpauseDOM.classList.add("pause"); } if (isMuted) { soundmuteDOM.classList.add("mute"); seekbarVolumeDOM.classList.add("disabled"); } else { videoDOM.volume = 0.5; document.querySelector('.sound #progress').style.width = '50%'; } makePlaylistElementActive(videoPlaylistDOM); } function toMinutes(seconds) { let tmpSeconds = seconds; let minuteCounter = 0; let finallTime = ""; while (true) { if (tmpSeconds < 60) { tmpSeconds = tmpSeconds.toString().padStart(2, '0'); minuteCounter = minuteCounter.toString().padStart(2, '0'); finallTime = `${minuteCounter}:${tmpSeconds}`; } tmpSeconds -= 60; minuteCounter++; if (tmpSeconds <= 0) break; } return finallTime; } function moveRangeSlider(element , event){ const coordinate = element.getBoundingClientRect(); const width = coordinate.width; const offset = { x: Math.round(coordinate.left), y: Math.round(coordinate.top), } const finallWidth = getPercentByNumber(Math.round(event.clientX - offset.x), width); return finallWidth; } function makePlaylistElementActive(elements){ Array.from(elements).forEach((element)=>{ element.classList.remove("active"); if(decodeURI(videoDOM.src).search(element.dataset.src) != -1){ element.classList.add("active"); } }); } function updateVideoPausePlayState(){ if(videoDOM.paused){ playpauseDOM.classList.remove("pause"); }else{ playpauseDOM.classList.add("pause"); } }
فایل main.css گرافیک سفارشی ویدیو پلیر
.container{ margin: 0 auto; width: 80%; text-align: center; direction: rtl; } #introduce{ display: block; width: 100%; font-size: 35px; font-weight: bold; color: white; padding-bottom: 5px; background-color: #4CAF50; text-decoration: none; margin-bottom: 15px; } /* Page Style */ .video-wrapper{ position: relative; } .video-player-wrapper{ position: relative; display: inline-block; } .video-controls{ width: 100%; height: 50px; bottom: 4px; left: 0; position: absolute; background-image: linear-gradient(transparent,rgba(0,0,0,.75)); } #my-custom-video-play{ width: 720px; border-radius: 4px 0 0 4px; position: relative; } #my-custom-video-play::-webkit-media-controls{ display:none !important; } #video-playlist{ background-color: #ff9800; width: 190px; height: 405px; margin: 0; padding: 5px; box-sizing: border-box; list-style: none; position: absolute; right: 58px; overflow-y: auto; } #video-playlist li{ text-align: right; cursor: pointer; margin-bottom: 10px; padding: 10px; } #video-playlist li:hover, #video-playlist li.active{ background-color: cyan; } .icon-player{ width: 18px; height: 18px; cursor: pointer; background-repeat: no-repeat; background-size: 18px; display: inline-block; position: absolute; bottom: 10px; } .icon-player.play-pause{ background-image: url(../img/play-90.png); left: 10px; } .icon-player.play-pause.pause{ background-image: url(../img/pause-90.png); } .icon-player.sound-mute{ background-image: url(../img/sound-90.png); right: 140px; } .icon-player.sound-mute.mute{ background-image: url(../img/mute-90.png); } .icon-player.full-screen{ background-image: url(../img/full-screen-90.png); right: 10px; } .seekbar{ background-color: rgb(255 255 255 / 22%); border-radius: 10px; height: 7px; bottom: 14px; position: absolute; cursor: pointer; } .seekbar #loaded{ background-color: rgba(255, 255, 255, 0.726); border-radius: 10px; position: absolute; left: 0; bottom: 0; width: 1%; height: 7px; z-index: 5; } .seekbar #remain{ cursor: default; } .seekbar #progress{ background-color: #ff9800; border-radius: 10px; position: absolute; left: 0; bottom: 0; width: 0%; height: 7px; z-index: 10; } .seekbar #progress #handler{ position: absolute; width: 14px; height: 14px; border-radius: 14px; background-color: #fff; bottom: -4px; right: -3px; z-index: 15; } .seekbar.timer{ width: 455px; left: 40px; } .seekbar.timer #remain{ position: absolute; color: white; right: -50px; bottom: -5px; direction: ltr; -moz-user-select: -moz-none; -khtml-user-select: none; -webkit-user-select: none; } .seekbar.sound{ width: 90px; right: 34px; } .seekbar.sound.disabled{ cursor: not-allowed; opacity: 0.4; } .seekbar.sound #progress #handler{ width: 4px; } .seekbar.sound #loaded{ width: 100%; } #preview-thumbnail{ width: 140px; position: absolute; left: 15px; top: 15px; padding: 15px; background-color: whitesmoke; border-radius: 8px; z-index: 20; display: none; } #preview-thumbnail img{ width: 100%; border-radius: 8px; }
لیست نظرات
سلام. میشه کاری کرد مسیر فایل روی سرور مخفی باشه یا کاری کرد که فیلم قابل دانلود نباشه؟
درود ، میشه این کار با استفاده از ساخت encode انحصاری برای ویدیو انجام داد . اما مبحث پیشرفته ای هست و توی چند تا مقاله نمیشه توضیح داد .
سلام وقتتون بخیر امکان استفاده از کدهای مورد نظر برای وردپرس وجود داره؟
سلام بله